使用 Lambda 时,映射集中的 Java 8 唯一键集很慢



谁能告诉我为什么在下面的代码中使用java 8 stream/lambda比a慢得多?

Set<Map<Path, String>> set = new HashSet<>();
Map<Path, String> map1 = new HashMap<>();
map1.put(Paths.get("foo"), "bar");
set.add(map1);
Map<Path, String> map2 = new HashMap<>();
map2.put(Paths.get("foo"), "ham");
set.add(map2);
long start = System.currentTimeMillis();
Set<Path> uniqueFromStream = set.stream().flatMap(m -> m.keySet().stream()).collect(Collectors.toSet());
System.err.println("miliseconds for streams: " + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
Set<Path> uniqueFromLoop = new HashSet<>();
for(final Map<Path,String> map : set){
  uniqueFromLoop.addAll(map.keySet());
}
System.err.println("miliseconds for loops: " + (System.currentTimeMillis() - start));

当我运行它时,平均流/lambda 为 63 毫秒,但每个循环为 0 毫秒!

基元循环总是比 lambda 更有效,尤其是在小集合上,因为它更"原生"。

另一方面,lambda 通过函数式编程更多地解释了开发人员的意图,并且您的代码更易于维护。

随着时间的推移,Lambda 将越来越高效,如果您在大型集合上并行使用它。

Trisha Gee在Devoxx Belgium有一个有趣的演讲 https://www.youtube.com/watch?v=dlzMV83RTtw,关于这个主题:

好吧,没有魔法。

流处理需要一点时间来初始化,并且使编译器更难优化代码。Lambda 调用会增加开销。当然,您最后要为收集步骤(Collectors.toSet())"付费"。

另一方面,for 循环更简单,并且由编译器积极优化/内联。

最新更新