为什么foreach lambda比其他循环慢得多?

ial*_*der 2 java optimization foreach lambda java-8

我有需要迭代的列表.我使用的是Java 8中的新foreach.我发现它比旧的不那么优雅的方法慢得多.我已经阅读了这个堆栈讨论,它更多地关注最佳实践,而不是真实世界的实现.我理解,对于lambda来说,还有额外的开销来源于方法传递,但我仍然不理解第一个和第三个案例之间的差异,并且我认为我可能错误地使用它.还没有为lambda实现优化,还是有更好的方法可以使用它们来获得更高的性能?下面是一个示例性示例,而不是我的实际代码.

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class Main {
        public static void main(String[] args) {

            List<Memes> memesList =
                    Arrays.asList(
                            new OldMemes(),
                            new TrendingMemes()
                    );

            //----------------------------Benchmark
            long start, end;
            start = System.nanoTime();
            System.out.format("for each started @%d\n", start);
            //Old way.
            for(Memes memes : memesList){
                memes.showMeme();
            }
            //-----------------------------Benchmark
            end = System.nanoTime();
            System.out.println((end - start));
            start = System.nanoTime();
            System.out.format("for started @%d\n", start);
            //Other way
            for(Iterator<Memes> i = memesList.iterator(); i.hasNext(); ) {
                i.next().showMeme();
            }
            //-----------------------------Benchmark
            end = System.nanoTime();
            System.out.println((end - start));
            start = System.nanoTime();
            System.out.format("for each lambda started @%d\n", start);

            //New way.
            memesList.forEach((memes) -> memes.showMeme());

            //-----------------------------Benchmark
            end = System.nanoTime();
            System.out.println((end - start));
            System.out.format("end @%d\n", end);
        }
    interface Memes {
        public void showMeme();
    }

    static class OldMemes implements Memes {

        @Override
        public void showMeme() {
            System.out.println("Id appetere senserit his, nonumes consulatu vel id.");
        }

    }

    static class TrendingMemes implements Memes {

        @Override
        public void showMeme() {
            System.out.println("Id appetere senserit his, nonumes consulatu vel id.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*aux 9

你的基准是非常错误的.您只为这两种技术应用一个循环(仅两个元素).你应该重复这个至少一万亿次.同时增加数组的大小,使用至少50个元素.接下来,在基准测试时不要打印到stdout.这需要花费太多时间并且是同步操作并且会产生错误的结果.

阅读本主题以获得更好的结果:如何在Java中编写正确的微基准测试?