gpt4 book ai didi

java - Stream.collect(groupingBy(identity(), counting()) 然后按值对结果进行排序

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:12:54 26 4
gpt4 key购买 nike

我可以collect a list of words into a bag (又名多集):

Map<String, Long> bag =
Arrays.asList("one o'clock two o'clock three o'clock rock".split(" "))
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

但是,不能保证袋子中的条目以任何特定顺序排列。例如,

{rock=1, o'clock=3, one=1, three=1, two=1}

我可以将它们放入列表中,然后使用我实现的值比较器对它们进行排序:

ArrayList<Entry<String, Long>> list = new ArrayList<>(bag.entrySet());
Comparator<Entry<String, Long>> valueComparator = new Comparator<Entry<String, Long>>() {

@Override
public int compare(Entry<String, Long> e1, Entry<String, Long> e2) {
return e2.getValue().compareTo(e1.getValue());
}
};
Collections.sort(list, valueComparator);

这给出了期望的结果:

[o'clock=3, rock=1, one=1, three=1, two=1]

有没有更优雅的方法来做到这一点?相信这是很多人都解决过的问题。我可以使用 Java Streams API 中内置的东西吗?

最佳答案

您不需要创建一个比较器,已经有一个用于此任务的比较器: Map.Entry.comparingByValue .这将创建一个比较器,用于比较 map 条目的值。在这种情况下,我们对它们的倒序感兴趣,因此我们可以:

Map.Entry.comparingByValue(Comparator.reverseOrder())

作为比较器。然后你的代码可以变成

Collections.sort(list, Map.Entry.comparingByValue(Comparator.reverseOrder()));

没有自定义比较器。


对结果 Map 进行排序关于它的值,您还可以使用 Stream 管道。此外,而不是调用 Stream.of(Arrays.asList("...").split(" ")) , 你可能想调用 Pattern.compile(" ").splitAsStream("...")如果您要处理很长的字符串。

Map<String, Long> bag =
Pattern.compile(" ")
.splitAsStream("one o'clock two o'clock three o'clock rock")
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
Map<String, Long> sortedBag =
bag.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(v1, v2) -> { throw new IllegalStateException(); },
LinkedHashMap::new
));

此代码创建映射条目的流,按值的相反顺序对其进行排序并将其收集到 LinkedHashMap 中保持相遇顺序。

输出:

{o'clock=3, rock=1, one=1, three=1, two=1}

或者,您可以查看 StreamEx图书馆,你可以拥有:

Map<String, Long> bag =
StreamEx.split("one o'clock two o'clock three o'clock rock", " ")
.sorted()
.runLengths()
.reverseSorted(Map.Entry.comparingByValue())
.toCustomMap(LinkedHashMap::new);

此代码对每个字符串进行排序,然后调用 runLengths() .此方法会将相邻的相等元素折叠成 Stream<String, Long>其中值是元素出现的次数。例如,在流 ["foo", "foo", "bar"] 上,此方法将生成 Stream [Entry("foo", 2), Entry("bar", 1)] .最后,这按值的降序排序并收集到 LinkedHashMap 中。 .

请注意,这会给出正确的结果,而无需执行 2 个不同的 Stream 管道。

关于java - Stream.collect(groupingBy(identity(), counting()) 然后按值对结果进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34859884/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com