当前位置:  开发笔记 > 编程语言 > 正文

Java Stream.concat VS Collection.addAll的性能

如何解决《JavaStream.concatVSCollection.addAll的性能》经验,为你挑选了1个好方法。

用于在流中组合两组数据.

Stream.concat(stream1, stream2).collect(Collectors.toSet());

要么

stream1.collect(Collectors.toSet())
       .addAll(stream2.collect(Collectors.toSet()));

哪个更有效,为什么?



1> NoDataFound..:

出于可读性和意图的考虑,Stream.concat(a, b).collect(toSet())比第二种方案更清晰.

为了问题," 什么是最有效的 ",这里是一个JMH测试(我想说我没有那么多使用JMH,可能有一些空间来改进我的基准测试):

使用JMH,使用以下代码:

package stackoverflow;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;

@State(Scope.Benchmark)
@Warmup(iterations = 2)
@Fork(1)
@Measurement(iterations = 10)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode({ Mode.AverageTime})
public class StreamBenchmark {
  private Set s1;
  private Set s2;

  @Setup
  public void setUp() {
    final Set valuesForA = new HashSet<>();
    final Set valuesForB = new HashSet<>();
    for (int i = 0; i < 1000; ++i) {
      valuesForA.add(Integer.toString(i));
      valuesForB.add(Integer.toString(1000 + i));
    }
    s1 = valuesForA;
    s2 = valuesForB;
  }

  @Benchmark
  public void stream_concat_then_collect_using_toSet(final Blackhole blackhole) {
    final Set set = Stream.concat(s1.stream(), s2.stream()).collect(Collectors.toSet());
    blackhole.consume(set);
  }

  @Benchmark
  public void s1_collect_using_toSet_then_addAll_using_toSet(final Blackhole blackhole) {
    final Set set = s1.stream().collect(Collectors.toSet());
    set.addAll(s2.stream().collect(Collectors.toSet()));
    blackhole.consume(set);
  }
}

你得到了这些结果(为了便于阅读,我省略了一些部分).

Result "s1_collect_using_toSet_then_addAll_using_toSet":
  156969,172 ±(99.9%) 4463,129 ns/op [Average]
  (min, avg, max) = (152842,561, 156969,172, 161444,532), stdev = 2952,084
  CI (99.9%): [152506,043, 161432,301] (assumes normal distribution)

Result "stream_concat_then_collect_using_toSet":
  104254,566 ±(99.9%) 4318,123 ns/op [Average]
  (min, avg, max) = (102086,234, 104254,566, 111731,085), stdev = 2856,171
  CI (99.9%): [99936,443, 108572,689] (assumes normal distribution)
# Run complete. Total time: 00:00:25

Benchmark                                                       Mode  Cnt       Score      Error  Units
StreamBenchmark.s1_collect_using_toSet_then_addAll_using_toSet  avgt   10  156969,172 ± 4463,129  ns/op
StreamBenchmark.stream_concat_then_collect_using_toSet          avgt   10  104254,566 ± 4318,123  ns/op

使用的版本Stream.concat(a, b).collect(toSet())应该更快(如果我读好JMH数字).

另一方面,我认为这个结果是正常的,因为你没有创建一个中间集(这有一些成本,即使有HashSet),并且正如在第一个答案的评论中所述,它Stream懒惰的连接.

使用分析器,您可能会看到哪个部分较慢.您可能还想使用toCollection(() -> new HashSet(1000))而不是toSet()查看问题在于增长HashSet内部哈希数组.

推荐阅读
乐韵答题
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有