Java Streams .max() 和 .min() 性能落后?

Posted

技术标签:

【中文标题】Java Streams .max() 和 .min() 性能落后?【英文标题】:Java Streams .max() and .min() lag in performance? 【发布时间】:2020-08-20 11:36:24 【问题描述】:

考虑以下 2 个示例。

1 使用流

myList.stream().map(this::getInt).max(Integer::compareTo);

2 老办法

int max = Integer.MIN_VALUE;
for (MyItem item : myList) 
    max = Math.max(max, getInt(item));    

以上getInt 方法接受MyItem 参数并返回int 结果。

在这里,与 #1 相比,#2 的延迟要低得多。有谁知道我为什么或有什么问题?

【问题讨论】:

声称的性能差异没有记录测量方法是毫无价值的。见How do I write a correct micro-benchmark in Java?,我敢打赌,你违反了一两条规则。一个有用的指针可能是Java lambdas 20 times slower than anonymous classes Q&A。 @Holger 你是在建议我用方法输入值吗? 不,我建议记录您如何得出第二个代码比第一个代码“延迟低得多”的结论。如果我们使用测量代码而不是感觉,请发布该代码。然后,我们可以告诉你你做错了什么。或者您可以按照已经发布的链接找到自己。 【参考方案1】:

您可能应该利用 Streams 的功能,这些功能应该可以优化这些情况。阅读 Streams 的文档,第一个示例显示了 IntStream 的优化路径。

https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html

     int max = myList.stream()
                      .mapToInt(this::getInt)
                      .max()
                      .orElse(Integer.MIN_VALUE);

【讨论】:

我在这里看不到.orElse(Integer.MIN_VALUE); 的任何用途。我错过了什么吗? sum() 对 0 个元素返回 0,max() 返回一个 OptionalInt。 max() 返回一个 OptionalInt 如果没有元素则为空。最好坚持使用它而不是将其转换为Integer.MIN_VALUE @YuriSchimke 您的回答很有帮助。但是,这样做并没有给我带来任何显着的性能提升【参考方案2】:
myList.stream().mapToInt(this::getInt).max()

试试mapping to an IntStreamIntStream 在内部与 ints 一起使用,这避免了装箱和拆箱 Integer 对象的开销。此外,IntStream.max() 不需要自定义比较器。

所以你认为突出的原因是“装箱”和“拆箱”?

如果不通过您的基准运行它,我不知道它是否会匹配for 循环的性能。但这将是一个进步。如果它不够好,那么我建议坚持使用循环,因为我看不到任何其他改进它的方法。

【讨论】:

我实际上尝试了您建议的 int 流方式。但我实际上看不到任何显着的性能改进。

以上是关于Java Streams .max() 和 .min() 性能落后?的主要内容,如果未能解决你的问题,请参考以下文章

Java 8 不止是Lambdas和Streams

使用 JDK8 和 lambda (java.util.stream.Streams.zip) 压缩流

Java 8 中的 Streams API 详解

java8的Streams

如何使用 Java Streams API 添加和更新地图条目

Java 8 中的 Streams API 详解