【发布时间】:2019-12-16 20:01:52
【问题描述】:
我目前正在进行一个项目,我正在使用 Java Microbenchmark Harness (JMH) 框架测量 Java 中不同类型循环的速度。我得到了一些关于流的有趣结果,但我无法解释,我想知道是否有更好地理解流和数组列表的人可以帮助我解释我的结果。
基本上,当遍历大小约为 100 的数组列表时,stream.forEach 方法比任何其他类型的循环都要快得多:
我的结果图表如下所示: https://i.imgur.com/ypXoWWq.png
我尝试过使用对象和字符串的数组列表,都产生了相似的结果。随着列表的大小变大,流方法仍然更快,但其他列表之间的性能差距会变小。我不知道是什么导致了这些结果。
@Fork(5)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 10, time = 100, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 100, timeUnit = TimeUnit.MILLISECONDS)
@State(Scope.Thread)
public class StackOverflowQ {
List<Integer> intList;
int size = 100;
@Setup
public void setup() {
intList = new ArrayList<>(size);
for(int i = 0; i<size;i++){
intList.add(i);
}
}
/**
Work done to each item in the loop.
*/
public double doWork(int item) {
return item + 47;
}
@Benchmark
public void standardFor(Blackhole bh){
for (int i = 0; i<intList.size(); i++){
bh.consume(doWork(intList.get(i)));
}
}
@Benchmark
public void streamForEach(Blackhole bh){
intList.stream().forEach(i -> bh.consume(doWork(i)));
}
}
【问题讨论】:
-
您是否尝试过从循环中提取
size()调用(使用size而不是intList.size()) - 检查stackoverflow.com/q/57414353/85421 -
查看这个关于流的优点和缺点的问题,这可能会有所帮助 -stackoverflow.com/questions/44180101
-
你能确认你的流是
sequential()吗?为了正确起见,我会将这个显式调用包含在您的基准测试中。 -
您还应该与
for(Integer i: intList) bh.consume(doWork(i));变体进行比较。此外,您可以直接在ArrayList上使用forEach,无需流。 -
两种方法怎么能给出四种结果?
标签: java loops for-loop java-stream jmh