Understanding Java foreach Loop Limitations and Proper Element Deletion/Modification
This article explains how Java's foreach loop iterates over arrays and collections, demonstrates why removing or reassigning elements within a foreach causes ConcurrentModificationException or has no effect, and shows the correct ways to delete or modify elements using traditional for loops or iterator methods, complete with code examples.
The author, a senior architect, discusses common questions about using foreach to delete or modify elements in Java collections.
(1) Traversing Elements
Example code for iterating over an array and an ArrayList :
String[] array = {"1", "2", "3"};
for (String i : array) {
System.out.println(i);
}
ArrayList
list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
for (String i : list) {
System.out.println(i);
}The output shows simple traversal of both structures.
Decompiled code reveals that array traversal uses a traditional for loop, while collection traversal uses an Iterator .
(2) Deleting Elements
Using a classic for loop to remove an element works:
ArrayList
list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
for (int i = 0; i < list.size(); i++) {
list.remove("222");
}
System.out.println(list); // [111, 333]Attempting the same with foreach throws ConcurrentModificationException because the iterator detects a structural change:
ArrayList
list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
for (String i : list) {
list.remove("222");
}
// Exception: java.util.ConcurrentModificationExceptionThe correct way is to use the iterator’s remove() method:
ArrayList
list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
Iterator
it = list.iterator();
while (it.hasNext()) {
String next = it.next();
if (next.equals("222")) {
it.remove();
}
}
System.out.println(list); // [111, 333](3) Modifying Elements
Replacing the whole element with a new value works with a classic for loop:
ArrayList
list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
for (int i = 0; i < list.size(); i++) {
list.set(i, "444");
}
System.out.println(list); // [444, 444, 444]Doing the same inside a foreach loop does not change the list because the loop variable is a copy: ArrayList list = new ArrayList<>(); list.add("111"); list.add("222"); list.add("333"); for (String i : list) { i = "444"; // has no effect on the list } System.out.println(list); // [111, 222, 333] However, modifying an object’s fields via foreach works because the reference points to the same object: public class Student { private int age; private String name; // getters and setters omitted for brevity } ArrayList studentList = new ArrayList<>(); studentList.add(new Student(1, "huge")); studentList.add(new Student(1, "xiaoyao")); for (Student stu : studentList) { stu.setName("jingtian"); } System.out.println(studentList.get(0).getName()); // jingtian System.out.println(studentList.get(1).getName()); // jingtian Summary Both for and foreach can traverse arrays and collections, but for is more flexible for complex operations. foreach cannot delete or replace collection elements directly; for or an iterator must be used. Both loops can modify the internal state of objects referenced in the collection. The article concludes that the traditional for loop offers greater flexibility for element manipulation in Java collections.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.