How to perform the below Scala operation to find the most frequent character in a string in java 8?
val tst = "Scala is awesomestttttts"
val op = tst.foldLeft(Map[Char,Int]())((a,b) => {
a+(b -> ((a.getOrElse(b, 0))+1))
}).maxBy(f => f._2)
Here the output is
(Char, Int) = (t,6)
I was able to get a stream of characters in Java 8 like this:
Stream<Character> sch = tst.chars().mapToObj(i -> (char)i);
but not able to figure out whats the fold/foldLeft/foldRight alternative we have in Java 8
Can someone pls help?
Something like this seems to match with the Scala code you provided (if I understand it correctly):
String tst = "Java is awesomestttttts";
Optional<Map.Entry<Character, Long>> max =
tst.chars()
.mapToObj(i -> (char) i)
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()))
.entrySet()
.stream()
.max(Comparator.comparing(Map.Entry::getValue));
System.out.println(max.orElse(null));
If you don't mind using a third-party library Eclipse Collections has a Bag
type that can keep track of the character counts. I've provided two examples below that use Bags. Unfortunately there is no maxByOccurrences
available today on Bag
, but the same result can be achieved by using topOccurrences(1)
which is available. You can also use forEachWithOccurrences
to find the max but it will be a little more code.
The following example uses a CharAdapter
, which is also included in Eclipse Collections.
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 on String
which returns an IntStream
. It feels a bit awkward that something called chars() does not return a CharStream, but this is because CharStream
is 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 converted the characters to lowercase first, so there are 5 occurrences of 's'. If you want uppercase and lowercase letters to be distinct then just drop the lowercase code in both examples.
Note: I am a committer for Eclipse Collections.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With