使用 collect 保留 Java 流中的顺序



我遇到了一些问题,我需要在对字符串列表执行的操作中保留顺序并使用 java 流 API 中的collect方法。

public List<String> countOccurrences(ArrayList<String> messages) {
List<String> stackedMessages = new LinkedList<>();
HashMap<String, Integer> messageOccurrences = 
messages.stream()
.collect(groupingBy(Function.identity(), summingInt(e -> 1)));
messageOccurrences.forEach((key, value) -> {
String appendString = value == 1 ? "" : " (" + value + " times)";
stackedMessages.add(key + appendString);
});
return stackedMessages;
}

上面代码的问题在于,如果我处理诸如["blah", "blah", "yep"]之类的列表,它会返回["yep", "blah (2 times)"]我需要它返回["blah (2 times)", "yep"]的位置。

我已经在这里看了这篇文章,并被引导相信如果我在已经排序的数据结构上使用流,那么将确保顺序:如何确保 java8 流中的处理顺序?

我想我需要将groupingBy更改为toMap,截至目前,我正在阅读该文档。任何精通该主题的人都请提供一些指示。

更新:

感谢用户@Aominè,这是使用分组的正确方法

.collect(groupingBy(Function.identity(),LinkedHashMap::new, summingInt(e->1)))

您需要收集到LinkedHashMap才能获得预期的结果。此外,您不必在groupingBy后与流管道分开执行另一个forEach,只需从entrySet创建一个流,然后map收集到列表即可。

return messages.stream()
.collect(groupingBy(Function.identity(), LinkedHashMap::new, summingInt(e -> 1)))
.entrySet()
.stream()
.map(e -> e.getKey()+(e.getValue() == 1 ? "" : " (" + e.getValue() +" times)"))
.collect(toList());

最新更新