Java 8 forEach Loop需要花费很多时间,为什么?

时间:2016-05-25 11:01:06

标签: java

我有一个围绕3483对象的ArrayList,它准备在数据库中合并。 当我使用lambda表达式时 - 它需要85122毫秒。 但是for(Obj o : list)只需要25毫秒。为什么Java8需要3404倍的时间?

List<CIBSubjectData> list1 = .....

list1.forEach(data ->
     merge(data)
);

for (CIBSubjectData data : list1) {
    merge(data);
}

1 个答案:

答案 0 :(得分:3)

我相信你没有使用合适的微基准设置。您正在比较bytecode instrumentation framework(用于在运行时生成lambda字节码的ASM)+ lambda execution timeexecution time of the loop的预热。

检查performance-difference-between-java-8-lambdas-and-anonymous-inner-classes和链接文档的答案。链接的文档深入了解了幕后的处理。

修改提供一个小片段来演示上述内容。

public class Warmup {
    static int dummy;

    static void merge(String s) {
        dummy += s.length();
        dummy++;
        dummy -= s.length();
    }

    public static void main(String[] args) throws IOException {
        List<String> list1 = new ArrayList<>();
        Random rand = new Random(1);

        for (int i = 0; i < 100_000; i++) {
            list1.add(Long.toString(rand.nextLong()));
        }

        // this will boostrap the bytecode instrumentation
        // Stream.of("foo".toCharArray()).forEach(System.out::println);
        long start = System.nanoTime();
        list1.forEach(data -> merge(data));

        long end = System.nanoTime();
        System.out.printf("duration: %d%n", end - start);
        System.out.println(dummy);
    }
}

如果您在发布时运行代码,则我的机器上的打印持续时间为

duration: 71694425

如果取消注释行Stream.of(...(第一次只使用字节码检测框架),则打印持续时间为

duration: 7516086

这只是初次运行的10%左右。

注意只是要明确。不要使用如上所述的基准测试。请查看jmh以了解此类要求。