Avoid Common Pitfalls When Removing Elements from Java Lists
This article explains why naïve removal of elements from a Java List can produce unexpected results or throw ConcurrentModificationException, and demonstrates seven safe techniques—including index adjustment, reverse iteration, and iterator‑based removal—along with code samples and detailed reasoning.
When deleting elements from a java.util.List, using list.remove(o) or list.remove(i) can easily lead to bugs such as skipped elements or ConcurrentModificationException. The article first shows a simple list initialization and prints [1, 2, 3, 3, 4].
1. Ordinary for‑loop removal (Incorrect)
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 3) list.remove(i);
}
System.out.println(list); // [1, 2, 3, 4]The loop removes only one occurrence of 3 because after a removal the subsequent elements shift left, causing the next duplicate to be skipped.
2. For‑loop with index decrement (Correct)
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 3) list.remove(i--);
}
System.out.println(list); // [1, 2, 4]Decrementing i after removal compensates for the left‑shift, ensuring all matching elements are processed.
3. Reverse iteration (Correct)
for (int i = list.size() - 1; i >= 0; i--) {
if (list.get(i) == 3) {
list.remove(i);
}
}
System.out.println(list); // [1, 2, 4]Iterating from the end avoids index‑shift problems entirely.
4. foreach loop removal (Incorrect)
for (Integer i : list) {
if (i == 3) list.remove(i);
}
System.out.println(list);This throws java.util.ConcurrentModificationException because the underlying iterator detects structural changes made outside its remove() method.
5. Iterator‑based removal (Correct)
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
if (it.next() == 3) {
it.remove();
}
}
System.out.println(list); // [1, 2, 4]Using the iterator’s own remove() method keeps modCount and expectedModCount in sync, preventing the exception.
6. list.remove(i) inside iterator loop (Incorrect)
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
Integer value = it.next();
if (value == 3) {
list.remove(value);
}
}
System.out.println(list);Directly calling list.remove(value) also triggers ConcurrentModificationException for the same reason as method 4.
7. Removing by value vs. by index
Calling list.remove(2) removes the element at index 2. To delete the Integer object 2, use list.remove(new Integer(2)), which invokes the remove(Object) overload.
Summary
When using a for‑loop to delete list elements, remember that removal shifts subsequent elements left, potentially skipping items.
The safest approach is to use an iterator’s remove() method or iterate in reverse order.
Be aware that list.remove(int) treats the argument as an index; to remove an object, pass an Integer instance.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
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.
