Why is the foreach lambda so much slower than the other for loops?

foreach, java, java-8, lambda, optimization

Solution

Your benchmark is terribly wrong. You only apply one loop (of only two elements) for both techniques. You should repeat this at least for a trillion times. Also increase the size of your array, use something of at least 50 elements. Next, do never print to stdout while benchmarking. That takes too much time and is a synchronized operation and will give wrong results.

Read this topic to get better results: How do I write a correct micro-benchmark in Java?

Problem

I have lists that I need to iterate through. I was using the new foreach from Java 8. I found it to be much slower than older less elegant methods. I've read this stack discussion which focuses more on best practices rather than real world implementation. I understand that with the lambda there is additional overhead that stems from method passing, but I still don't understand the discrepancy between the first and third case and that has me thinking I could be using it wrong. Are there not yet implemented optimizations for the lambda or is there a better way I could be using them to get more performance? Below is a demonstrative sample and not my actual code. ``` 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."); } } } ```

Original source

Related problems