我遇到了一些问题,我需要在对字符串列表执行的操作中保留顺序并使用 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());