首页 > 解决方案 > Java .forEach(list::add) 与 .collect(Collectors.toList())

问题描述

什么更快?

List<E> bar = new ArrayList<>();
pan.stream() /* other functions */.forEach(bar::add);

或者

List<E> bar = pan.stream() /* other functions */.collect(Collectors.toList());

标签: javaperformancejava-stream

解决方案


我已经针对 100 万份的列表测试了这两种情况。总的来说,顺序流几乎没有区别,但并行流有区别:

Benchmark                    Mode  Cnt  Score    Error   Units
Performance.collect          avgt  200  0.022 ±  0.001   s/op
Performance.forEach          avgt  200  0.021 ±  0.001   s/op
Performance.collectParallel  avgt  200  0.124 ±  0.004   s/op
Performance.forEachParallel  avgt  200  0.131 ±  0.001   s/op

在我看来,您不应该使用列表,forEach因为它违反了函数纯度规则,并且在与并行流一起使用时收集更有效。

@Benchmark @BenchmarkMode(Mode.AverageTime)
public void collect(Blackhole blackhole) {
    Stream<Double> stream = Stream.iterate(0.0, e -> Math.random());
    List<Double> list = stream.limit(1000000).collect(Collectors.toList());
    blackhole.consume(list);
}

@Benchmark @BenchmarkMode(Mode.AverageTime)
public void forEach(Blackhole blackhole) {
    Stream<Double> stream1 = Stream.iterate(0.0, e -> Math.random());
    List<Double> list = new ArrayList<>();
    stream1.limit(1000000).forEach(e -> list.add(e));
    blackhole.consume(list);
}

@Benchmark @BenchmarkMode(Mode.AverageTime)
public void collectParallel(Blackhole blackhole) {
    Stream<Double> stream = Stream.iterate(0.0, e -> Math.random());
    List<Double> list = stream.parallel().limit(1000000).collect(Collectors.toList());
    blackhole.consume(list);
}

@Benchmark @BenchmarkMode(Mode.AverageTime)
public void forEachParallel(Blackhole blackhole) {
    Stream<Double> stream1 = Stream.iterate(0.0, e -> Math.random());
    List<Double> list = Collections.synchronizedList(new ArrayList<>());
    stream1.parallel().limit(1000000).forEach(e -> list.add(e));
    blackhole.consume(list);
}

推荐阅读