8 Reliable Ways to Remove Elements from a Java List (And Why Some Fail)
This article examines eight common techniques for deleting elements from a Java List, explains why certain loop‑based approaches cause errors or unexpected results, and highlights the three reliable methods—including reverse for‑loops, iterator.remove, and Stream filtering—that work correctly.
During a recent conversation a developer struggled to delete elements from a Java
Listand encountered runtime errors. The article analyzes why this happens and presents several ways to perform the deletion correctly.
Problem
Given the following list:
<code>public List<String> initList = Arrays.asList("张三", "李四", "周一", "刘四", "李强", "李白");</code>How can we remove all elements whose name starts with "李"?
Methods
We analyze several possible implementations.
1. Ordinary for loop deletion (unreliable)
<code>/**
* 普通 for 循环删除
*/
@Test
public void remove1() {
List<String> list = new ArrayList(initList);
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
if (str.startsWith("李")) {
list.remove(i);
}
}
System.out.println(list);
}
</code>Output:
[张三, 周一, 刘四, 李白]The loop uses
list.size()that changes during iteration, causing the loop to terminate early and leave some elements undeleted.
2. Ordinary for loop with size variable (throws exception)
<code>/**
* 普通 for 循环删除(size提出变量)
*/
@Test
public void remove2() {
List<String> list = new ArrayList(initList);
int size = list.size();
for (int i = 0; i < size; i++) {
String str = list.get(i);
if (str.startsWith("李")) {
list.remove(i);
}
}
System.out.println(list);
}
</code>Result: an
IndexOutOfBoundsExceptionbecause
sizeis fixed while the actual list shrinks.
3. Ordinary for loop reverse order (reliable)
<code>/**
* 普通 for 循环倒序删除
*/
@Test
public void remove3() {
List<String> list = new ArrayList(initList);
for (int i = list.size() - 1; i > 0; i--) {
String str = list.get(i);
if (str.startsWith("李")) {
list.remove(i);
}
}
System.out.println(list);
}
</code>Output:
[张三, 周一, 刘四]Iterating backwards prevents index shifting issues, making this approach safe.
4. Enhanced for loop deletion (throws exception)
<code>/**
* 增强 for 循环删除
*/
@Test
public void remove3() {
List<String> list = new ArrayList(initList);
for (String element : list) {
if (element.startsWith("李")) {
list.remove(element);
}
}
System.out.println(list);
}
</code>Result:
java.util.ConcurrentModificationExceptionbecause the underlying iterator detects concurrent modification.
5. Iterator loop with iterator.remove() (reliable)
<code>/**
* 迭代器循环删除(iterator.remove)
*/
@Test
public void remove4() {
List<String> list = new ArrayList(initList);
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String str = iterator.next();
if (str.contains("李")) {
iterator.remove();
}
}
System.out.println(list);
}
</code>Output:
[张三, 周一, 刘四]The iterator’s
removemethod synchronizes the expected modification count, avoiding the concurrent‑modification error.
6. Iterator loop with list.remove (throws exception)
<code>/**
* 迭代器循环删除(list.remove)
*/
@Test
public void remove5() {
List<String> list = new ArrayList(initList);
for (Iterator<String> ite = list.iterator(); ite.hasNext(); ) {
String str = ite.next();
if (str.contains("李")) {
list.remove(str);
}
}
System.out.println(list);
}
</code>Result: another
ConcurrentModificationExceptionbecause removal is performed on the list rather than through the iterator.
7. Collection forEach deletion (throws exception)
<code>/**
* list.forEach 删除
*/
@Test
public void remove6() {
List<String> list = new ArrayList(initList);
list.forEach((e) -> {
if (e.contains("李")) {
list.remove(e);
}
});
System.out.println(list);
}
</code>Result:
ConcurrentModificationExceptionbecause
forEachinternally uses an iterator.
8. Stream filter (reliable)
<code>/**
* stream filter 过滤
*/
@Test
public void remove7() {
List<String> list = new ArrayList(initList);
list = list.stream().filter(e -> !e.startsWith("李")).collect(Collectors.toList());
System.out.println(list);
}
</code>Output:
[张三, 周一, 刘四]This approach leverages the Stream API to create a new list without the unwanted elements, offering concise and safe removal.
Summary
The article presents eight ways to delete elements from a Java
List. Only three methods are reliable: reverse‑order for loops, iterator‑based removal, and Stream filtering. The other approaches either miss elements or raise
ConcurrentModificationException, illustrating common pitfalls for developers.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
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.