Stream VS ForEach

最近一直在使用 Stream API,但是到底流式操作,自动装箱对性能的影响如何,一直没有一个明确的答案,看 Java8 In Action 的时候,看到这个例子,自己也测了下, 基本与书中描述一直。对于合格的 Java 开发者,有个基本的认识是必须的。

package com.example.test;

import java.util.function.Function;
import java.util.stream.LongStream;
import java.util.stream.Stream;

public class BenchSum {

    public static long measureSumPerf(Function<Long, Long> adder, long n)
    {
        long fastest = Long.MAX_VALUE;
        for (int i = 0; i < 20; i++) {
            long start = System.nanoTime();
            long sum = adder.apply(n);
            long duration = (System.nanoTime() - start) / 1_000_000;
            //System.out.println("Result: " + sum);
            if (duration < fastest)
            {
                fastest = duration;
            }
        }
        return fastest;
    }

    public static long sequentialSum(long n) {
        return Stream.iterate(1L, i -> i + 1)
                .limit(n)
                .reduce(0L, Long::sum);
    }

    public static long iterativeSum(long n) {
        long result = 0;
        for (long i = 1L; i <= n; i++)
        {
            result += i;
        }
        return result;
    }

    public static long iterativeSumAutoBox(long n) {
        Long result = 0L;
        for (Long i = 1L; i <= n; i++)
        {
            result += i;
        }
        return result.longValue();
    }

    public static long rangeClosed(long n)
    {
        return LongStream.rangeClosed(1L, n)
                .reduce(0L, Long::sum);
    }

    public static long parallelSum(long n)
    {
        return Stream.iterate(1L, i -> i + 1)
                .limit(n)
                .parallel()
                .reduce(0L, Long::sum);
    }

    public static long parallelRangeSum(long n)
    {
        return LongStream.rangeClosed(1L, n)
                .parallel()
                .reduce(0L, Long::sum);
    }

    public static void main(String[] args) {
        System.out.println("Sequential sum done in : " + measureSumPerf(BenchSum::sequentialSum, 10_000_000) + "m_secs");
        System.out.println("Iterative sum done in : " + measureSumPerf(BenchSum::iterativeSum, 10_000_000) + "m_secs");
        System.out.println("Iterative autobox sum done in : " + measureSumPerf(BenchSum::iterativeSumAutoBox, 10_000_000) + "m_secs");
        System.out.println("LongStream sum done in : " + measureSumPerf(BenchSum::rangeClosed, 10_000_000) + "m_secs");
        System.out.println("LongStream parallel sum done in : " + measureSumPerf(BenchSum::parallelRangeSum, 10_000_000) + "m_secs");
        System.out.println("parallel sum done in : " + measureSumPerf(BenchSum::parallelSum, 10_000_000) + "m_secs");
    }
}

我的运行结果:

Sequential sum done in : 81m_secs
Iterative sum done in : 3m_secs
Iterative autobox sum done in : 56m_secs
LongStream sum done in : 4m_secs
LongStream parallel sum done in : 2m_secs
parallel sum done in : 287m_secs

结论:

  1. 自动装箱的性能开销在大数据量的程序中是不可忽略的。
  2. stream API 与 For 循环性能相当,可以放心使用
  3. 当使用并行流的时候,要做测试,有时候并行流不如串行流

你可能感兴趣的:(java)