Performance Comparison of Looping Through a List

Java provides many ways to iterate over a List. Some of them are using :

We are not going through the basics of each of the above ways as it is beyond the scope of this article, and most of us are already well aware.

In this post, we will compare all the looping methods against the same set of data for comparing their relative performances.

1. Different Methods to Loop Through a List

We are listing down 4 different ways which are in my knowledge.

1.1. Stream API

Java 8 Stream API provides the ways to iterate over a collection and operate over each element. Stream can be used as an alternative to the for-loop.

private static List<Integer> list = new ArrayList<>();

list.stream().forEach(consumerAction);

1.2. Enhanced for-loop

In this technique, advanced for-each statement introduced in Java 5 is used.

private static List<Integer> list = new ArrayList<>();
for(Integer i : list)
{
    // do other stuff
}

1.3. ListIterator Interface

private static List<Integer> list = new ArrayList<>();

list.listIterator().forEachRemaining(consumerAction);

1.4. Simple for-loop

private static List<Integer> list = new ArrayList<>();
int size = list.size();
for(int j = 0; j < size ; j++)
{
    //do stuff
}

2. Performance Comparison

We are creating an ArrayList and populating it with one million Integer instances. Then we will iterate through the list using all the above ways. This way we will be able to understand the difference in the performance.

2.1. Execution environment

2.2. Source Code

package com.howtodoinjava.core.basic;

import java.util.ArrayList;
import java.util.List;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.infra.Blackhole;

public class ForLoopPerformanceTest 
{
    public static void main(String[] args) throws Exception {
        org.openjdk.jmh.Main.main(args);
    }
    
    private static List<Integer> list = new ArrayList<>();
    static
    {
        for(int i=0; i < 1_000_000; i++)
        {
            list.add(i);
        }
    }
    
    @Benchmark
    @Fork(value = 1, warmups = 1)
    @BenchmarkMode(Mode.Throughput)
    public void usingStream(Blackhole blackhole) {
        list.stream().forEach(i -> blackhole.consume(i));
    }
    
    @Benchmark
    @Fork(value = 1, warmups = 1)
    @BenchmarkMode(Mode.Throughput)
    public void usingIterator(Blackhole blackhole) {
        list.listIterator().forEachRemaining(i -> blackhole.consume(i));
    }
    
    @Benchmark
    @Fork(value = 1, warmups = 1)
    @BenchmarkMode(Mode.Throughput)
    public void usingForEachLoop(Blackhole blackhole) {
        for(Integer i : list)
        {
           blackhole.consume(i);
        }
    }
    
    @Benchmark
    @Fork(value = 1, warmups = 1)
    @BenchmarkMode(Mode.Throughput)
    public void usingSimpleForLoop(Blackhole blackhole) {
        for(int i = 0; i < list.size() ; i++)
        {
            blackhole.consume(i);
        }
    }
}

When the above JMH based benchmarking runs, the following is the output in the console:

Benchmark                                   Mode  Cnt    Score    Error  Units
ForLoopPerformanceTest.usingForEachLoop    thrpt   20  259.008 ± 17.888  ops/s
ForLoopPerformanceTest.usingIterator       thrpt   20  256.016 ± 10.342  ops/s
ForLoopPerformanceTest.usingSimpleForLoop  thrpt   20  495.308 ± 12.866  ops/s
ForLoopPerformanceTest.usingStream         thrpt   20  257.174 ± 15.880  ops/s

Clearly, using the simple for-loop is way ahead in the performance. Rest other three ways provide similar performance numbers.

3. Conclusion

Although the simple for-loop provides the best performance, other looping methods provide much better readability.

Also, we are using the loop with over one million items in the list which is not a very practical scenario in most of the applications.

So if there are not millions of items in the list, use the new Java features such as Stream API or enhanced for-loops.

Happy Learning !!

Was this post helpful?

Join 7000+ Awesome Developers

Get the latest updates from industry, awesome resources, blog updates and much more.

* We do not spam !!

8 thoughts on “Performance Comparison of Looping Through a List”

  1. Type-0: Using [ while ( iterator.hasNext() ) ]                           :: 27 ms
    Type-1: Using [ for(Integer i : list) ]                                  :: 25 ms
    Type-2: Using [ for(int j = 0; j < list.size() ; j++) ]                  :: 7 ms
    Type-3: Using [ int size = list.size(); for(int j = 0; j < size ; j++) ] :: 7 ms
    Type-4: Using [ for(int j = list.size(); j > 0 ; j--) ]                  :: 6 ms
    Type-5: Using [ int size = list.size(); for(int j = size; j > 0 ; j--) ] :: 8 ms
    
    Reply
    • Once you add a simple integer sum accesing elements in the array list, the difference vanishes with performance evens out. Note the first method “Type-0” is old iterator based.

      Type-0: Using [ while ( iterator.hasNext() ) ]                           :: 47 ms
      Type-1: Using [ for(Integer i : list) ]                                  :: 27 ms
      Type-2: Using [ for(int j = 0; j < list.size() ; j++) ]                  :: 27 ms
      Type-3: Using [ int size = list.size(); for(int j = 0; j < size ; j++) ] :: 26 ms
      Type-4: Using [ for(int j = list.size(); j > 0 ; j--) ]                  :: 23 ms
      Type-5: Using [ int size = list.size(); for(int j = size; j > 0 ; j--) ] :: 24 ms
      
      Reply
  2. Also, the for-each loop runs significantly faster in cases such as a LinkedLIst, where the data is not stored in a sequential space in memory. In fact, it takes FOREVER (not literally) to use the non-for-each loops on a LinkedList.
    Having a fair understanding of how what you’re using works is fairly important to knowing how to optimize your code.

    Reply
  3. I have searched for the performance of loop over the internet and no-one article says about the low performance of first loop(i.e. for-each loop). Moreover many people have given the JAVA doc specification saying that:——-
    “The for-each loop, introduced in release 1.5, gets rid of the clutter and the opportunity for error by hiding the iterator or index variable completely. The resulting idiom applies equally to collections and arrays. Note that there is no performance penalty for using the for-each loop, even for arrays. In fact, it may offer a slight performance advantage over an ordinary for loop in some circumstances, as it computes the limit of the array index only once. While you can do this by hand, programmers don’t always do so.”

    Reply
    • Hi Shivam,

      Please refer to https://stackoverflow.com/questions/6839494/enhanced-for-loop-performance-worse-than-traditional-indexed-lookup.

      I can give you 10 more links which hints for slower performance.

      The reason “for-each” loop is thought better is because of its readability. Its easier to write and understand the statement. The difference for looping a large collection is a rare condition and also the time advantage is not very attractive [but its there, you can verify yourself] .

      Reply
      • Enhanced For loop will make the loops easier to write but as you mentioned it does come with some performance penalty.

        Sometime back I’ve done the tests myself to assess different for loops and found the Enhanced for loop to be 13-15x slower than the normal for loop.But I’ve made few mistakes like you.
        In the tests that you’ve mentioned in this article, I don’t see any warm-up phase before your actual measurement starts So I’m wondering about the results that you’ve posted here. Is it from a single run or an average of say 1Million runs. Also JVM does lot of optimizations if a loop/method is recognized as Hot (used frequently). So it would be better to do some warmup before starting our timer or use tools like JMH to assess the performance of different versions. Also as Rajesh mentioned, most of the times we use for loop to iterate over a collection of user defined objects like Person. In that case we need to check which is significantly faster.

        for(int i=0,j = list.size(); i < j; i++){
        Person p = list.get(i);
        // do something with p
        }

        for(Person p: list){
        // do something with p
        }

        I'll post my findings using JMH as soon as I find time 🙂

        Reply

Leave a Comment

HowToDoInJava

A blog about Java and related technologies, the best practices, algorithms, and interview questions.