If you do not mind using the third-party Eclipse Collection library, Bag type that can track the number of characters. I have given two examples below that use Bags. Unfortunately, today there is no maxByOccurrences on Bag , but the same result can be achieved using topOccurrences(1) , which is available. You can also use forEachWithOccurrences to search for max, but that will be a bit more code.
The following example uses the CharAdapter , which is also included in the Eclipse collection.
MutableBag<Character> characters = CharAdapter.adapt("Scala is awesomestttttts") .collect(Character::toLowerCase) .toBag(); MutableList<ObjectIntPair<Character>> charIntPairs = characters.topOccurrences(2); Assert.assertEquals( PrimitiveTuples.pair(Character.valueOf('t'), 6), charIntPairs.get(0)); Assert.assertEquals( PrimitiveTuples.pair(Character.valueOf('s'), 5), charIntPairs.get(1));
The second example uses the chars() method, available in String , which returns an IntStream . It feels a little uncomfortable that something called chars () does not return CharStream, but that is because CharStream not available in JDK 8.
MutableBag<Character> characters = "Scala is awesomestttttts" .toLowerCase() .chars() .mapToObj(i -> (char) i) .collect(Collectors.toCollection(Bags.mutable::empty)); MutableList<ObjectIntPair<Character>> charIntPairs = characters.topOccurrences(2); Assert.assertEquals( PrimitiveTuples.pair(Character.valueOf('t'), 6), charIntPairs.get(0)); Assert.assertEquals( PrimitiveTuples.pair(Character.valueOf('s'), 5), charIntPairs.get(1));
In both examples, I first converted the characters to lowercase, so there are 5 occurrences of 's'. If you want uppercase and lowercase letters to be legible, just drop the lowercase code in both examples.
Note: I am a committer for Eclipse collections.