Avoid Common Java List Pitfalls: Immutable Collections, SubList, and foreach Errors
This article explains why Java's Arrays.asList and List.subList can produce unexpected behavior, how mutable and immutable List implementations interact with their backing arrays, and provides safe alternatives and best practices to prevent ConcurrentModificationException and hidden memory leaks.
ArrayList: Real or Fake?
Using Arrays.asList returns a fixed‑size list backed by the original array, not a true java.util.ArrayList, so any add or remove operation throws UnsupportedOperationException.
Debugging shows the returned list is actually an internal class java.util.Arrays$ArrayList, which does not override mutating methods from AbstractList, causing the exception.
New List Still Affects the Original Array
The list returned by Arrays.asList shares the same underlying array. Modifying an element in the list also changes the original array, and vice‑versa.
arrays:[modify_1, modify_2, 3]
list:[modify_1, modify_2, 3]Because the implementation uses the original array, both views stay in sync.
Wrapping the array with a real ArrayList breaks the link:
List<String> list = new ArrayList<>(Arrays.asList(arrays));Guava also provides a concise way:
List<String> list = Lists.newArrayList(arrays);SubList Shares the Parent List
List.subListcreates a view that holds a reference to the original list. Any modification to the sub‑list actually changes the parent list, which can lead to unexpected memory retention and even OOM errors.
Example output shows the parent list and sub‑list stay synchronized:
integerList:[10, 20, 3]
subList:[10, 20]Immutable Collections Are Not Truly Immutable
Creating an unmodifiable list with Collections.unmodifiableList prevents direct modifications, but if the underlying mutable list changes, the “immutable” view reflects those changes.
Both JDK 9’s List.of and Guava’s ImmutableList.copyOf create truly independent collections; the Guava approach is shorter and easier to use.
List<String> list = new ArrayList<>(Arrays.asList("one", "two", "three"));
List<String> unmodifiableList = ImmutableList.copyOf(list);foreach Loop Add/Remove Pitfall
Removing elements from a list while iterating with a foreach loop causes a ConcurrentModificationException because the loop is compiled to use an Iterator that checks a modification count.
java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:939)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:893)Safe alternatives are:
Use Iterator.remove() inside an explicit iterator loop.
Use Java 8’s List.removeIf method.
Summary
Do not assume Arrays.asList or List.subList return independent ArrayList instances; always wrap them in a real ArrayList when you need a mutable, independent collection.
JDK’s built‑in immutable collections are heavyweight and can still reflect changes to the backing list; prefer Guava’s immutable collections for safety and performance.
Avoid modifying a list inside a foreach loop; use an explicit iterator or removeIf instead.
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.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
