Java 8流:将Map<K,V>转换为List<T>

27

假设我有一个接受两个参数并返回一个值的函数,那么是否可能将Map转换为List并在Stream中作为非终端操作?

最接近的方法似乎是对Map使用forEach创建实例并将它们添加到预定义的List中,然后从该List开始新的Stream。或者是我错过了什么?

例如:经典问题“在一长串单词中找到出现频率最高的3个单词”。

wordList.stream().collect(groupingBy(Function.identity, Collectors.counting))).

现在我想要流式传输该地图的entrySet

sorted((a,b) -> a.getValue().compareTo(b.getValue))).limit(3).forEach(print...
2个回答

56
你应该获取map的entrySet,并将这些条目粘合到二元函数的调用中:
inputMap.entrySet().stream().map(e->myFun(e.getKey(),e.getValue()));

上述操作的结果是一系列 T 实例的流。
更新
您提供的额外示例证实了下面评论中讨论的内容:按组和排序本质上都是终端操作。必须完全执行它们才能产生输出的第一个元素,因此将它们作为非终端操作涉及到性能/内存占用方面并没有任何优势。
Java 8 将 sorted 定义为非终端操作,这可能会导致代码具有迷惑性,因为该操作将阻塞直到接收到所有上游元素,并且在接收时必须保留它们全部。

2
答案中的代码接受一个 map 并生成 T 实例的流。没有任何关于列表的痕迹。 - Marko Topolnik
2
你获取了一个 entrySet 流 - 是的,我明白。但是如果 Map 是在流的中间创建的(例如通过 collect 方法),并且我想将 k,v 条目转换为一个单一类型的流,并继续处理这些流中的元素,你该如何做到呢? - JamesCherrill
1
collect是一个终端操作,它不能出现在流的中间。 如果您想要一个生成值对的流步骤,然后是一个将它们折叠成单个值的后续步骤,那么您需要一个Pair<K,V>容器类。 - Marko Topolnik
2
如果您需要确保对的唯一性,则在流中涉及distinct()步骤。 - Marko Topolnik
1
作为比较,Clojure 不会将排序作为懒序列提供。 - Marko Topolnik
显示剩余5条评论

0

您也可以使用以下技巧将Hashmap条目转换为ArrayList,

ArrayList list = hashMap.values();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接