Skip to content
CMO & CTO
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

  • Digital Experience
    • Experience Strategy
    • Experience-Driven Commerce
    • Multi-Channel Experience
    • Personalization & Targeting
    • SEO & Performance
    • User Journey & Behavior
  • Marketing Technologies
    • Analytics & Measurement
    • Content Management Systems
    • Customer Data Platforms
    • Digital Asset Management
    • Marketing Automation
    • MarTech Stack & Strategy
    • Technology Buying & ROI
  • Software Engineering
    • Software Engineering
    • Software Architecture
    • General Software
    • Development Practices
    • Productivity & Workflow
    • Code
    • Engineering Management
    • Business of Software
    • Code
    • Digital Transformation
    • Systems Thinking
    • Technical Implementation
  • About
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

Enhanced for loop in Java 5

Posted on June 3, 2006 By Luis Fernandez

I keep running into moments where the enhanced for loop in Java 5 turns a messy block into something I can read in one sip of coffee.

J2SE 5.0 brought shiny stuff like generics and annotations, yet the quiet hero for day to day code is the foreach style loop. The syntax is short, the intent is clear, and it works with arrays and anything that implements Iterable. If you have been doing the old dance with index variables or juggling an Iterator, this will feel like switching from a stick shift to an automatic in rush hour. Before Java 5 most of my loops looked like this:

// list
for (int i = 0; i < list.size(); i++) {
    Thing t = (Thing) list.get(i); // casts everywhere before generics
    t.process();
}

// iterator
for (Iterator it = list.iterator(); it.hasNext(); ) {
    Thing t = (Thing) it.next();
    t.process();
}

// array
for (int i = 0; i < arr.length; i++) {
    int n = arr[i];
    sum += n;
}

Now the loop reads like the intent in my head. One element at a time, no ceremony, no noise. With the enhanced for loop the same code becomes:

for (Thing t : list) {
    t.process();
}

for (int n : arr) {
    sum += n;
}

The rule of thumb is simple. If you want to iterate without caring about the position, use the new loop. It works for arrays and for any collection that exposes an Iterator. Under the covers it calls that iterator for you, so you get the same behavior with nicer clothes. With generics the types read well too. No more raw casts sprinkled all over the place. For example, a List<String> loops like this:

List<String> names = new ArrayList<String>();
names.add("Ada");
names.add("Linus");
names.add("Grace");

for (String name : names) {
    System.out.println(name.toUpperCase());
}

Maps deserve a quick note because they are not directly iterable by entry unless you ask them to be. If you want keys, loop over map.keySet(). If you want values, map.values(). If you want both in a tight loop, use entrySet so you do not trigger an extra lookup for each value. With generics this reads clean and avoids casts:

Map<String, Integer> ages = new HashMap<String, Integer>();
ages.put("Alice", 31);
ages.put("Bob", 28);

// keys
for (String user : ages.keySet()) {
    System.out.println(user);
}

// values
for (Integer age : ages.values()) {
    total += age;
}

// entries
for (Map.Entry<String, Integer> e : ages.entrySet()) {
    System.out.println(e.getKey() + " => " + e.getValue());
}

There are trade offs. The new loop is not a match when you need the index. If you must peek at neighbors, write into a specific position, or zip two lists by index, keep the classic loop. You also do not get removal for free. If you call remove on the collection while inside the foreach loop, you will meet a ConcurrentModificationException. The safe route for removals during traversal is to reach for the iterator and call remove() on it:

for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
    Thing t = it.next();
    if (t.isStale()) {
        it.remove(); // safe removal during iteration
    }
}

One more spot where the old pattern stays handy is when you want to write back into the same array or list at a position. You can read with foreach, but you cannot set by index through it. In that case the plain loop still wins clarity:

for (int i = 0; i < scores.size(); i++) {
    scores.set(i, scores.get(i) + bonus);
}

What about performance. For arrays the foreach loop compiles into the same kind of iteration you would write by hand. For collections it is the iterator path you already use. The gain is not in microseconds but in readability and fewer silly mistakes. Shorter loops mean fewer variables, fewer casts, and fewer off by one bugs. When I revisit code after a week, the foreach version explains itself with less brain power. That is the real win for me. I can skim a file and spot the business rules without tripping over scaffolding.

Quick tip if you are introducing this to a codebase that still has raw types. Add generics as you touch a class. The compiler will guide you. Then switch loops where it makes sense. It lands well in reviews because the diff gets smaller and the intent gets bolder. And if you adopt enums or autoboxing in the same pass, the code starts to feel modern without a giant rewrite.

Use foreach for clear read only traversal of arrays and collections, keep the classic loop when you need the index or safe in place edits.

For maps prefer entrySet() in hot loops, and reach for the iterator when you need removal during the walk.

Code Development Practices Software Engineering coding-practicesjavaspring

Post navigation

Previous post
Next post
  • Digital Experience (94)
    • Experience Strategy (19)
    • Experience-Driven Commerce (5)
    • Multi-Channel Experience (9)
    • Personalization & Targeting (21)
    • SEO & Performance (10)
  • Marketing Technologies (92)
    • Analytics & Measurement (14)
    • Content Management Systems (45)
    • Customer Data Platforms (4)
    • Digital Asset Management (8)
    • Marketing Automation (6)
    • MarTech Stack & Strategy (10)
    • Technology Buying & ROI (3)
  • Software Engineering (310)
    • Business of Software (20)
    • Code (30)
    • Development Practices (52)
    • Digital Transformation (21)
    • Engineering Management (25)
    • General Software (82)
    • Productivity & Workflow (30)
    • Software Architecture (85)
    • Technical Implementation (23)
  • 2025 (12)
  • 2024 (8)
  • 2023 (18)
  • 2022 (13)
  • 2021 (3)
  • 2020 (8)
  • 2019 (8)
  • 2018 (23)
  • 2017 (17)
  • 2016 (40)
  • 2015 (37)
  • 2014 (25)
  • 2013 (28)
  • 2012 (24)
  • 2011 (30)
  • 2010 (42)
  • 2009 (25)
  • 2008 (13)
  • 2007 (33)
  • 2006 (26)

Ab Testing Adobe Adobe Analytics Adobe Target AEM agile-methodologies Analytics architecture-patterns CDP CMS coding-practices content-marketing Content Supply Chain Conversion Optimization Core Web Vitals customer-education Customer Data Platform Customer Experience Customer Journey DAM Data Layer Data Unification documentation DXP Individualization java Martech metrics mobile-development Mobile First Multichannel Omnichannel Personalization product-strategy project-management Responsive Design Search Engine Optimization Segmentation seo spring Targeting Tracking user-experience User Journey web-development

©2025 CMO & CTO | WordPress Theme by SuperbThemes