Java中的流比本地循环慢得多-为什么?

时间:2019-06-14 10:47:21

标签: java java-8 java-stream

据我了解,流比传统的旧编程要快。

但是,当我运行以下代码时,结果却出乎我的意料。

public class Application {
    public static void main(String[] args) {
        long startTime = System.nanoTime();
        int[] a = { 1, 2, 3, 4 };
        int m = Arrays.stream(a).reduce(Integer.MIN_VALUE, Math::max);
        long endTime = System.nanoTime();
        long totalTime = endTime - startTime;
        System.out.println(totalTime);

    }
}

输出为:22857304

public class Application {
        public static void main(String[] args) {
        long startTime = System.nanoTime();
        int[] a = { 1, 2, 3, 4 };
        int e = a.length;
        int m = Integer.MIN_VALUE;
        for (int i = 0; i < e; i++)
            if (a[i] > m)
                m = a[i];
        long endTime = System.nanoTime();
        long totalTime = endTime - startTime;
        System.out.println(totalTime);
    }
}

输出为:1459

请帮助我了解为什么流这么慢?

2 个答案:

答案 0 :(得分:4)

完全解释这将花费大量时间;但是您在这里测试的是“冷”启动,基本上没有太多JIT,并且简单的循环不会像Stream解决方案那样分配对象-因此时间要少得多。流具有可运行的基础结构-需要一段时间才能“加热”以提高性能。

代码的这些部分也不相同,就像您正在使用Math::max一样,在其中一个部分则是普通的>。您可以反复测试该代码,然后查看结果,但是即使如此,您可能仍应使用针对微基准量身定制的工具,据我所知JMH(和Google的Caliper-我只相信第一个。)

使用JMH,您可以完全不使用JIT,C1C2编译器或其他设置来测试这些方法,有关某些设置的示例,请参见this answer < / p>

答案 1 :(得分:0)

良好的旧式原始类型循环(例如 int [] )会更快,因为您可以直接访问索引存储结构。此外,编译器在优化这些操作方面非常有效。

流的实现取决于诸如List,ArrayList之类的数据结构,然后需要使用迭代器,并且不要忘记对原始类型<-> Object进行装箱和拆箱。

如果不使用int []而是使用ArrayList运行测试,则可能会得到更接近的结果。

此外,您可以利用流并行化的优势,以提高性能。 (取决于您的核心)

Arrays.stream(ints).parallel()

可以在这里找到很好的比较和解释:https://jaxenter.com/java-performance-tutorial-how-fast-are-the-java-8-streams-118830.html