whi*_*mot 9 java java-8 java-stream
我可以将一个单词列表收集到一个包中(也称为多组):
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()));
Run Code Online (Sandbox Code Playgroud)
但是,包的条目不保证按任何特定顺序排列.例如,
{rock=1, o'clock=3, one=1, three=1, two=1}
Run Code Online (Sandbox Code Playgroud)
我可以将它们放入列表中,然后使用我的值比较器实现对它们进行排序:
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);
Run Code Online (Sandbox Code Playgroud)
这给出了期望的结果:
[o'clock=3, rock=1, one=1, three=1, two=1]
Run Code Online (Sandbox Code Playgroud)
有没有更优雅的方式来做到这一点?我敢肯定这是很多人必须解决的问题.我可以使用Java Streams API内置的东西吗?
Tun*_*aki 10
您不需要创建比较器,已经有一个用于此任务:Map.Entry.comparingByValue.这将创建一个比较器,用于比较地图的条目值.在这种情况下,我们对它们的逆序感兴趣所以我们可以:
Map.Entry.comparingByValue(Comparator.reverseOrder())
Run Code Online (Sandbox Code Playgroud)
作为比较器.然后你的代码就可以了
Collections.sort(list, Map.Entry.comparingByValue(Comparator.reverseOrder()));
Run Code Online (Sandbox Code Playgroud)
没有自定义比较器.
要对结果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
));
Run Code Online (Sandbox Code Playgroud)
此代码创建地图条目的流,按值的相反顺序对其进行排序,并将其收集到a中LinkedHashMap以保持遭遇顺序.
输出:
{o'clock=3, rock=1, one=1, three=1, two=1}
Run Code Online (Sandbox Code Playgroud)
或者,您可以查看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);
Run Code Online (Sandbox Code Playgroud)
此代码对每个String进行排序,然后调用runLengths().此方法将相邻的相等元素折叠到一个Stream<String, Long> 值,即元素出现的次数.例如,在Stream上["foo", "foo", "bar"],此方法将生成Stream [Entry("foo", 2), Entry("bar", 1)].最后,这是按值的降序排序并收集到一个LinkedHashMap.
请注意,这样可以得到正确的结果,而无需执行2个不同的Stream流水线.
| 归档时间: |
|
| 查看次数: |
5519 次 |
| 最近记录: |