How for-each works in Java: analysis with examples from beginner to pro

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: why did for-each become the "king" of loops in Java?

\n\n

If you've been writing Java for at least a week, you've definitely encountered the construct for (Type var : collection). This concise syntax is called the for-each loop (or enhanced for loop). It appeared back in Java 5 (2004) and quickly became a favorite among developers.

\n\n

But do you know what happens under the hood when the JVM encounters this construct? Why can for-each be slower than a regular for loop for arrays? And why does it sometimes throw ConcurrentModificationException, even if you're not deleting anything?

\n\n

In this article, we will analyze how for-each works in Java at the bytecode level, compare it with classic loops, and learn how to avoid typical pitfalls. Let's go!

\n\n

Syntax and first acquaintance

\n\n

The basic syntax looks like this:

\n\n
for (ElementType variable : collection_or_array) {\n    // loop body\n}
\n\n

Example with ArrayList:

\n\n
List<String> names = Arrays.asList("Anna", "Boris", "Victor");\n\nfor (String name : names) {\n    System.out.println("Hello, " + name + "!");\n}
\n\n

Output:

\n\n
Hello, Anna!\nHello, Boris!\nHello, Victor!
\n\n

Simple, right? Yes. But behind this simplicity lie two completely different mechanisms — for arrays and for collections.

\n\n

How does for-each work with arrays?

\n\n

When you write a for-each loop for an array, the Java compiler turns it into a regular index-based for loop. No magic.

\n\n

Your code:

\n\n
int[] numbers = {10, 20, 30};\n\nfor (int num : numbers) {\n    System.out.println(num);\n}
\n\n

After compilation (decompile the bytecode — check for yourself):

\n\n
int[] numbers = new int[]{10, 20, 30};\nfor (int i = 0; i < numbers.length; i++) {\n    int num = numbers[i];\n    System.out.println(num);\n}
\n\n

Important conclusion: for arrays, for-each and the regular for loop are the same in terms of performance. No iterator overhead.

\n\n

How does for-each work with collections (List, Set)?

\n\n

Now here's where it gets interesting. For collections, for-each uses an iterator.

\n\n

Your code:

\n\n
List<String> list = new ArrayList<>();\nlist.add("Java");\nlist.add("Python");\nlist.add("C++");\n\nfor (String lang : list) {\n    System.out.println(lang);\n}
\n\n

The compiler transforms this into:

\n\n
List<String> list = new ArrayList<>();\nlist.add("Java");\nlist.add("Python");\nlist.add("C++");\n\nfor (Iterator<String> it = list.iterator(); it.hasNext(); ) {\n    String lang = it.next();\n    System.out.println(lang);\n}
\n\n

That is:

\n
    \n
  • list.iterator() is called — we get an iterator.
  • \n
  • The condition is it.hasNext().
  • \n
  • In the body — it.next().
  • \n
  • The variable lang is initialized with the result of next().
  • \n
\n\n

What does this mean in practice?

\n
    \n
  • You cannot remove elements inside a for-each loop using list.remove() — you will get a ConcurrentModificationException. Use it.remove() or a regular for loop.
  • \n
  • You cannot modify the collection (add/remove) during iteration — same error.
  • \n
  • Performance: for ArrayList, the difference from a regular for loop is minimal (creating an iterator object). For LinkedList — for-each is much faster than for (int i = 0; i < list.size(); i++), because get(i) for LinkedList is O(n) each time!
  • \n
\n\n

What about Map? Iterating over key-value pairs

\n\n

Map does not directly implement Iterable, so for-each

Blogs

Book Recommendations