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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了按Stream API的频率对集合进行排序相关的知识,希望对你有一定的参考价值。

大家好,每个人都在使用溪流,有这样一个问题。我有一张表,我想根据其中出现的字符的频率进行排序:

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

我写了这个方法:

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());

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

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

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

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

如何改进?

答案

你可以这样做,

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));

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

请注意,此处未使用mergeFunction,因为没有键冲突。

另一答案

删除.limit(limit),因为它导致Stream管道只处理第一个limit元素(根据你的输出,limit6)。

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());

输出:

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

以上是关于按Stream API的频率对集合进行排序的主要内容,如果未能解决你的问题,请参考以下文章

按 C 中元素出现频率的降序对数组进行排序

使用 Stream API 简化集合操作

使用 Linq 按名称频率对列表进行排序

首先按频率对字符串中的字符进行排序,然后按字母顺序排序

在python中,如何按元素的频率对列表进行排序

在结构中按频率对数组中的字母进行排序