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 IntStream
。 IntStream
在内部与 int
s 一起使用,这避免了装箱和拆箱 Integer
对象的开销。此外,IntStream.max()
不需要自定义比较器。
所以你认为突出的原因是“装箱”和“拆箱”?
如果不通过您的基准运行它,我不知道它是否会匹配for
循环的性能。但这将是一个进步。如果它不够好,那么我建议坚持使用循环,因为我看不到任何其他改进它的方法。
【讨论】:
我实际上尝试了您建议的 int 流方式。但我实际上看不到任何显着的性能改进。以上是关于Java Streams .max() 和 .min() 性能落后?的主要内容,如果未能解决你的问题,请参考以下文章
使用 JDK8 和 lambda (java.util.stream.Streams.zip) 压缩流