Mefisto_Fell
Mefisto_Fell

Reputation: 916

Sort the collection by frequency of the Stream API

Hello everyone working with streams, there was such a question. I have a sheet that I want to sort by the frequency of occurrence of characters in it:

List<String> frequency = new ArrayList<>();
        Collections.addAll(frequency, "gg", "ss", "gg", "boy", "girls", "girls", "gg", "boy", "aa", "aa");

I wrote this method:

return words.stream().limit(limit).map(String::toLowerCase)
.collect(Collectors.groupingBy(Function.identity(),Collectors.counting()))
                    .entrySet().stream()
                    .map(entry -> new Pair<>(entry.getKey(), entry.getValue()))
                    .collect(Collectors.toList());

But the answer is already displayed is not correct, the string a is completely lost, the string gg is one element, and the boys is one element

ss=1
gg=2
girls=2
boy=1

And I don’t know how to sort them by frequency of occurrence. The result should be like this:

gg=3
aa=2
boy=2
girls=2
ss=1

How can this be improved?

Upvotes: 3

Views: 2217

Answers (2)

Ravindra Ranwala
Ravindra Ranwala

Reputation: 21124

You may do it like so,

Map<String, Long> wordCount = frequency.stream()
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
    .entrySet().stream()
    .sorted(Map.Entry.<String, Long>comparingByValue(Comparator.reverseOrder())
        .thenComparing(Map.Entry.comparingByKey()))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, 
        (e1, e2) -> e2, LinkedHashMap::new));

Output: {gg=3, aa=2, boy=2, girls=2, ss=1}

Notice that the mergeFunction is NOT used here since there are no key conflicts.

Upvotes: 5

Eran
Eran

Reputation: 393811

Remove .limit(limit), since it causes the Stream pipeline to process only the first limit elements (based on your output, limit was 6).

return 
   frequency.stream()
            .map(String::toLowerCase)
            .collect(Collectors.groupingBy(Function.identity(),Collectors.counting()))
            .entrySet().stream()
            .map(entry -> new SimpleEntry<>(entry.getKey(), entry.getValue()))
            .collect(Collectors.toList());

Output:

[aa=2, ss=1, gg=3, girls=2, boy=2]

Upvotes: 1

Related Questions