集合之List--List如何安全删除

在java中,List的删除操作可能会导致ConcurrentModificationException一场,尤其是在遍历时直接调用removce(方法)

一、使用Iterator删除

Iterator提供了安全的删除方法remove(),可以在遍历时删除元素

List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
​
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    if (item.equals("B")) {
        iterator.remove(); // 安全删除
    }
}
​
System.out.println(list); // 输出: [A, C]

优点:

  • 安全且高效

  • 适用于单线程环境

二、使用removeIf(方法)(java8+)

java8引入了removeIf方法,可以根据条件删除元素

List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
​
list.removeIf(item -> item.equals("B")); // 删除满足条件的元素
​
System.out.println(list); // 输出: [A, C]

优点

  • 代码简洁,适合函数式编程风格。

  • 内部使用 Iterator,安全高效。

三、使用for循环倒序遍历

如果使用普通的for循环删除元素,建议倒序遍历,避免索引错误问题

List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
​
for (int i = list.size() - 1; i >= 0; i--) {
    if (list.get(i).equals("B")) {
        list.remove(i); // 删除元素
    }
}
​
System.out.println(list); // 输出: [A, C]

优点

  • 避免索引错位问题。

  • 适用于需要根据索引删除的场景。

四、使用CopyOnWriteArrayList

如果需要在多线程环境下安全删除元素,可以使用CopyOnWriteArrayList,它在修改时创建底层数据的新副本,适合多读写啊后的场景

List<String> list = new CopyOnWriteArrayList<>();
list.add("A");
list.add("B");
list.add("C");
​
for (String item : list) {
    if (item.equals("B")) {
        list.remove(item); // 安全删除
    }
}
​
System.out.println(list); // 输出: [A, C]

注意

  • CopyOnWriteArrayList 的写操作性能较差,因为每次修改都会创建新副本。

  • 适合多线程环境。

五、使用Collections.synchronizedList加锁

如果使用Collecions.synchronizedList包装List,需要手动加锁以保证线程安全

List<String> list = Collections.synchronizedList(new ArrayList<>());
list.add("A");
list.add("B");
list.add("C");
​
synchronized (list) {
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {
        String item = iterator.next();
        if (item.equals("B")) {
            iterator.remove(); // 安全删除
        }
    }
}
​
System.out.println(list); // 输出: [A, C]

优点

  • 线程安全。

  • 适用于多线程环境

六、使用Stream过滤

如果需要删除满足条件的元素并生成新表,可以使用Stream的filter方法

List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
​
List<String> result = list.stream()
                          .filter(item -> !item.equals("B")) // 过滤掉 "B"
                          .collect(Collectors.toList());
​
System.out.println(result); // 输出: [A, C]

优点

  • 不修改原列表,生成新列表。

  • 适合函数式编程风格。

总结

方法适用场景特点
Iterator.remove()单线程环境安全高效
removeIf()Java 8+,单线程环境简洁,适合函数式编程
倒序遍历 for 循环根据索引删除避免索引错位
CopyOnWriteArrayList多线程环境线程安全,适合读多写少
Collections.synchronizedList + 锁多线程环境线程安全,需要手动加锁
Stream.filter()生成新列表不修改原列表,适合函数式编程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值