HowToDoInJava

  • Python
  • Java
  • Spring Boot
  • Dark Mode
Home / Java / Collections Framework / Performance Comparison – Different For Loops in Java

Performance Comparison – Different For Loops in Java

For loop is very common control flow statement in programming languages such as java. I am not going to describe the basics of “for loop” as it is beyond the scope of this article and most of us are already well aware of this.

In this post, I will list down various ways to use for loop in day-to-day programming habits and then I will compare them against a similar set of data for their relative performances.

Different ways to use for loop

I am listing down 4 different ways in my knowledge. If you know any other way also, please let me know through a comment.

1) For each statement

In this technique, advanced for each statement introduced in java 5 is used. Learn this also as your next core java interview question.

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

2) Using list.size() in condition

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

3) Initialize another local variable with size

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

4) Initialize the initial value of counter to size of list

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

Comparing the performance of all types

I am creating an arraylist and populate it with 1 crore Integer instances. Then I will iterate through the list using all four ways. This way we will be able to understand the different in performance.

Execution environment:

  • Java 7
  • Eclipse Juno
package com.howtodoinjava.demo.core;

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

public class ForLoopPerformanceTest
{
	private static List<Integer> list = new ArrayList<>();
	private static long startTime;
	private static long endTime;
	static
	{
		for(int i=0; i < 1_00_00_000; i++)
		{
			list.add(i);
		}
	}
	@SuppressWarnings("unused")
	public static void main(String[] args)
	{
		//Type 1
		startTime = Calendar.getInstance().getTimeInMillis();
		for(Integer i : list)
		{
			//
		}
		endTime = Calendar.getInstance().getTimeInMillis();
		System.out.println("For each loop :: " + (endTime - startTime) + " ms");

		//Type 2
		startTime = Calendar.getInstance().getTimeInMillis();
		for(int j = 0; j < list.size() ; j++)
		{
			//
		}
		endTime = Calendar.getInstance().getTimeInMillis();
		System.out.println("Using collection.size() :: " + (endTime - startTime) + " ms");

		//Type 3
		startTime = Calendar.getInstance().getTimeInMillis();
		int size = list.size();
		for(int j = 0; j < size ; j++)
		{
			//System.out.println(j);
		}
		endTime = Calendar.getInstance().getTimeInMillis();
		System.out.println("Using [int size = list.size(); int j = 0; j < size ; j++] :: " + (endTime - startTime) + " ms");

		//Type 4
		startTime = Calendar.getInstance().getTimeInMillis();
		for(int j = list.size(); j > size ; j--)
		{
			//System.out.println(j);
		}
		endTime = Calendar.getInstance().getTimeInMillis();
		System.out.println("Using [int j = list.size(); j > size ; j--] :: " + (endTime - startTime) + " ms");
	}
}

When above program runs, following is the output in console:

For each loop :: 110 ms
Using collection.size() :: 37 ms
Using [int size = list.size(); int j = 0; j < size ; j++] :: 4 ms
Using [int j = list.size(); j > size ; j--] :: 1 ms

Clearly the last two ways are way ahead in terms of performance, while for each statement [type 1] is most expensive operation if compared with other three.

Update:

Reason for difference in performance

Last two flavors type 3 and 4 have a very little difference and should be considered as same. They both fetch the size of collection initially. And then uses this size value in loop for checking the condition.

Type 2 uses size() method call every time and thus on runtime it brings a little overhead. Though JVM optimizes this code as inline call and other optimizations also and size method is simply a getter for size attribute of instance of list. Even though it brings a few more statements to execute at machine level code and which makes the difference.

Type 1 is costliest one and simple reasoning is the use of iterator internally created in for each loop. Creating an iterator and calling iterator.get() adds up to most of cost which is not involved in direct access in other three types.

Happy Learning !!

Share this:

  • Twitter
  • Facebook
  • LinkedIn
  • Reddit

About Lokesh Gupta

A family guy with fun loving nature. Love computers, programming and solving everyday problems. Find me on Facebook and Twitter.

Feedback, Discussion and Comments

  1. Henry Nguyen

    December 1, 2016

    I believe you did this test wrongly, type 3 and 4 didn’t even access the elements inside the array, just iterate from 1 -> 100k and doing nothing.
    On the other hand type 1 was really accessing the elements in the array.
    Please update this post accordingly since many people are thinking type 3 and 4 really make a big improvement which is mistaken.

  2. NA

    July 6, 2016

    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
    
    • NA

      July 6, 2016

      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
      
  3. sudheer

    March 13, 2015

    Any Thoughts on Why Type 4 is better than Type 3 ?

    • Lokesh Gupta

      March 15, 2015

      Only one call to size() method.

    • Noah

      March 15, 2016

      Type 3 is also being charged for the int size = list.size(); which Type 4 then later uses without having to set up the variable

    • mike

      December 20, 2018

      The type 4 should be,
      for(int j = list.size(); j > 0 ; j–)
      {
      //System.out.println(j);
      }
      original code is,
      for(int j = list.size(); j > size ; j–)
      …
      the loop will not be executed.

  4. walid

    November 21, 2014

    in //Type 4 for(int j = list.size(); j > size ; j–)
    you loop from size to size -> 0 iteration

  5. Sushil

    October 16, 2014

    I was thinking about the time difference,Then this came in my mind & below are the results.
    Please use the loop what it is meant for:-

    List list = new ArrayList();
    long startTime;
    long endTime;
    for (int i = 0; i < 10000000; i++) {
    list.add(i);
    }
    // Type 1
    startTime = Calendar.getInstance().getTimeInMillis();
    for (Integer i : list) {
    int a = i;
    }
    endTime = Calendar.getInstance().getTimeInMillis();
    System.out.println("For each loop :: " + (endTime – startTime) + " ms");

    // Type 2
    startTime = Calendar.getInstance().getTimeInMillis();
    for (int j = 0; j < list.size(); j++) {
    int a = list.get(j);
    }
    endTime = Calendar.getInstance().getTimeInMillis();
    System.out.println("Using collection.size() :: " + (endTime – startTime) + " ms");

    // Type 3
    startTime = Calendar.getInstance().getTimeInMillis();
    int size = list.size();
    for (int j = 0; j < size; j++) {
    int a = list.get(j);
    }
    endTime = Calendar.getInstance().getTimeInMillis();
    System.out.println("Using [int size = list.size(); int j = 0; j 0; j–) {
    int a = list.get(j);
    }
    endTime = Calendar.getInstance().getTimeInMillis();
    System.out.println(“Using [int j = list.size(); j > size ; j–] :: ” + (endTime – startTime) + ” ms”);

    For each loop :: 32 ms
    Using collection.size() :: 27 ms
    Using [int size = list.size(); int j = 0; j size ; j–] :: 22 ms

  6. Rinkesh

    June 11, 2014

    Article is good but you forgot main thing in analysis and that is “Accessing actual values from the list”. You are just comparing how much time LOOP will take. But if for case 3/4, if you try to access list value for that index then you will see actual performance. In that case, First is clear winner. Try it.

  7. pravnviji

    January 8, 2014

    Type 4 is not good to use because values are not accessed. Using of Type 3 is efficient. BTW this is good tutorial.

  8. Fla

    December 18, 2013

    Effectively, some tests where wrong (type4) and the it tests nothing if value is not accessed…

    But, something else has not been taken in advice with these tests : I’have added tests at startup of my swing application and the order of the tested methods changes the results.

    I think the memory used by previous tests objects should be garbaged during next test… Then i have added System.gc(); before each tests and results are now really differents :

    Using [Iterator iter = list.iterator(); iter.hasNext();] :: 42 ms : TOTAL = -2014260032
    Using [Integer i : list] :: 45 ms : TOTAL = -2014260032
    Using [int j = 0; j = 0 ; j–] :: 54 ms : TOTAL = -2014260032
    Using [int j = 0; j < size ; j++] :: 48 ms : TOTAL = -2014260032

    • Lokesh Gupta

      December 18, 2013

      Thanks for sharing your observations.

  9. Nitin Gautam

    November 8, 2013

    What is the best practices of looping while retrieving data from Record set ?

  10. Trinea

    October 28, 2013

    there is a bit error in type 4, it should be
    for(int j = list.size() – 1; j >= 0 ; j–)

  11. Jacob Zimmerman

    October 21, 2013

    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.

  12. Rehman

    September 5, 2013

    Good Article…

  13. Subrat

    June 28, 2013

    Its nice!!! previously I also had a view that foreach loop gives better performance.Thanks for clarifying.

  14. Vo2

    April 30, 2013

    Well …

    1)
    If you make a loop, you obviously need to access the values …
    So add Integer i = list.get(j) for types >=2

    2)

    Your Type 4 may need to be debugged …
    1 + 2 =>
    Type 1 is something le 25% slower than the 3 others
    (no differences between them)

    • Jacob Zimmerman

      October 21, 2013

      Type 4 should be “for(int j = list.size() – 1; j >= 0 ; –j)”
      Even with the added access, mine average out to about 35 for type 1 and 30 for the others.

  15. Shivam Gupta

    April 5, 2013

    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.”

    • Lokesh Gupta

      April 5, 2013

      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] .

      • Rajesh

        October 26, 2013

        If we are dealing with collections, and trying to address each of the collection object in that case for each loop is faster. Instead of using the increment variable “i” to get the object at index “i”.

        • Arkantos

          July 5, 2014

          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 🙂

          • Lokesh Gupta

            July 5, 2014

            Fair enough. I didn’t do stuffs like warm-up, and these tests are very basic observations.

Comments are closed on this article!

Search Tutorials

Java Collections

  • Collections Framework
  • Array
  • ArrayList
  • LinkedList
  • HashMap
  • Hashtable
  • LinkedHashMap
  • TreeMap
  • HashSet
  • LinkedHashSet
  • TreeSet
  • Comparable
  • Comparator
  • Iterator
  • ListIterator
  • Spliterator
  • PriorityQueue
  • PriorityBlockingQueue
  • ArrayBlockingQueue
  • LinkedTransferQueue
  • CopyOnWriteArrayList
  • CopyOnWriteArraySet
  • Collection Sorting
  • Interview Questions

Java Tutorial

  • Java Introduction
  • Java Keywords
  • Java Flow Control
  • Java OOP
  • Java Inner Class
  • Java String
  • Java Enum
  • Java Collections
  • Java ArrayList
  • Java HashMap
  • Java Array
  • Java Sort
  • Java Clone
  • Java Date Time
  • Java Concurrency
  • Java Generics
  • Java Serialization
  • Java Input Output
  • Java New I/O
  • Java Exceptions
  • Java Annotations
  • Java Reflection
  • Java Garbage collection
  • Java JDBC
  • Java Security
  • Java Regex
  • Java Servlets
  • Java XML
  • Java Puzzles
  • Java Examples
  • Java Libraries
  • Java Resources
  • Java 14
  • Java 12
  • Java 11
  • Java 10
  • Java 9
  • Java 8
  • Java 7

Meta Links

  • About Me
  • Contact Us
  • Privacy policy
  • Advertise
  • Guest and Sponsored Posts

Recommended Reading

  • 10 Life Lessons
  • Secure Hash Algorithms
  • How Web Servers work?
  • How Java I/O Works Internally?
  • Best Way to Learn Java
  • Java Best Practices Guide
  • Microservices Tutorial
  • REST API Tutorial
  • How to Start New Blog

Copyright © 2020 · HowToDoInjava.com · All Rights Reserved. | Sitemap

  • Java 15 New Features
  • Sealed Classes and Interfaces
  • EdDSA (Ed25519 / Ed448)