Reputation: 15
I have List with single letters inside. I need to count all duplicates and find the most frequent duplicate. The list generates randomly, so it may contain several most frequent letters.
Is it possible to create only one map inside one Stream or put the second map inside Stream? I need only one Stream chain, using the method groupingBy().
public static void mostFrequentlyDuplicateLetters(List<String> letters) {
Map<String, Long> collect = letterList
.stream()
.collect(Collectors.groupingBy(String::valueOf, Collectors.counting()))
.entrySet()
.stream()
.filter(// How to find the most frequent letters and put them on a map?))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
Upvotes: 1
Views: 834
Reputation: 29028
it may contain several most frequent letters
The solution below allows to determine all the letters
from the given list that have a maximum frequency
.
public static void main(String[] args) {
Map<String, Long> frequencies = getFrequencyMap(List.of("A", "B", "B", "C", "C", "C", "B", "D"));
long max = getMaxFrequency(frequencies);
System.out.println("max = " + max);
System.out.println(mostFrequentlyDuplicateLetters(frequencies, max));
}
public static Map<String, Long> getFrequencyMap(List<String> letters) {
return letters.stream()
.collect(Collectors.groupingBy(UnaryOperator.identity(), Collectors.counting()));
}
public static long getMaxFrequency(Map<String, Long> frequencies) {
return frequencies.values().stream()
.mapToLong(Long::longValue)
.max()
.orElse(0);
}
public static List<String> mostFrequentlyDuplicateLetters(Map<String, Long> frequencies,
long frequency) {
return frequencies.entrySet().stream()
.filter(entry -> entry.getValue() == frequency)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
output (both letters B
and C
have frequency = 3)
max = 3
[B, C]
Is it possible to create only one map inside one Stream
If you want your code to be both efficient and clean the answer is NO
. By trying to fuse more than one concern in one method you'll violate the first of the SOLID principles - The single responsibility principle
.
Upvotes: 1
Reputation: 444
First of all what you need as your return type is actually Map.Entry
, not the whole Map, since you just want an entry with highest number of occurrences.
You can try this way:
public Map.Entry<String,Long> mostFrequentlyDuplicateLetters(List<String> letterList){
return letterList
.stream()
.collect(Collectors.groupingBy(String::valueOf, Collectors.counting()))
.entrySet()
.stream().max(Map.Entry.comparingByValue())
.get();
}
Upvotes: 2