我遇到了一个问题,我需要在对字符串列表执行的操作中保留顺序,并使用java stream 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"]
。
我已经在这里查看了这篇文章,并且相信如果我在已经排序的数据结构上使用流,那么将确保订单:How to ensure order of processing in java8 streams?
我想我需要将groupingBy
更改为toMap
,现在我正在阅读该文档。任何精通这一主题的人都已经提出了一些建议。
更新:
感谢用户@Aominè,这是使用groupingBy
执行此操作的正确方法.collect(groupingBy(Function.identity(),LinkedHashMap::new, summingInt(e->1)))
答案 0 :(得分:1)
您需要收集到LinkedHashMap
才能获得预期结果。此外,您不必在forEach
之后与流管道分开执行另一个groupingBy
,只需从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());