按Stream API的频率对集合进行排序

Mef*_*ell 3 java lambda java-8 java-stream

大家好,使用streams时,有一个问题。我有一个工作表,我想按其中出现字符的频率进行排序:

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

我写了这个方法:

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());
Run Code Online (Sandbox Code Playgroud)

但是已经显示的答案是不正确的,字符串a完全丢失,字符串gg是一个元素,而boy是一个元素

ss=1
gg=2
girls=2
boy=1
Run Code Online (Sandbox Code Playgroud)

而且我不知道如何按发生频率对它们进行排序。结果应该是这样的:

gg=3
aa=2
boy=2
girls=2
ss=1
Run Code Online (Sandbox Code Playgroud)

如何改善呢?

Rav*_*ala 5

你可以这样做

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));
Run Code Online (Sandbox Code Playgroud)

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

注意,这里没有使用mergeFunction,因为没有键冲突。