集合遍历时删除元素的几种方法

@SpringBootTest
public class RemoveTest {

    List<Transaction> list = new ArrayList<>();

    @Before
    public void init() {
        list.add(new Transaction("test123"));
        list.add(new Transaction("123test"));
    }

    @After
    public void print() {
        list
                .stream()
                .forEach(System.out::println);
    }

    /**
     * 删除条件
     * @param transaction
     * @return
     */
    public boolean needDel(Transaction transaction) {
        return Character.isDigit(transaction.getReferenceCode().charAt(0));
    }

    /**
     * foreach 的时候 修改集合(新增/删除) 会触发fast-fail机制,报错
     */
    @Test
    public void test0() {
        for(Transaction t:list) {
            if(this.needDel(t))  {
                list.remove(t);
            }
        }
    }

    /**
     * remove if
     */
    @Test
    public void test1() {
        list.removeIf(this::needDel);
    }

    /**
     * 使用迭代器删除
     */
    @Test
    public void test2() {
        Iterator<Transaction> iterator = list.iterator();
        while (iterator.hasNext()){
            Transaction transaction = iterator.next();
            if(this.needDel(transaction)) {
                iterator.remove();
            }
        }
    }

    /**
     * stream filter
     */
    @Test
    public void test3() {
        list = list
                .stream()
                .filter(v->!this.needDel(v))
                .collect(Collectors.toList());
    }


    /**
     * 使用并发安全的集合类删除
     */
    @Test
    public void test4() {
        list = new CopyOnWriteArrayList<>(list);
        for(Transaction t:list) {
            if(this.needDel(t))  {
                list.remove(t);
            }
        }
    }


}

fast-fail机制

在系统设计的时候优先考虑异常的情况, 一旦发生异常, 直接停止并上报

例:

集合中的fast-fail机制:

在test0方法中, 在集合遍历的过程中添加删除元素, 会抛出ConcurrentModificationException,

在遍历的过程中, 检测到对象的并发修改, 但不允许这种修改, 就会抛出该异常

在集合的内部存在两个变量

modCount:表示该集合实际被修改的次数

expectModCount:表示迭代器预期,该集合被修改的次数, 只有通过迭代器对该集合操作时,该值才会改变

在遍历的过程中检测到两个值不相等,就会抛出ConcurrentModificationException,提示并发修改

fail-safe机制:

为了避免fast-fail机制, java 提供了fail-safe机制的集合类(java.util.concurrent包下),例如CopyOnWriteArrayList, 可以在多线程下并发修改

CopyOnWriteArrayList在添加/删除元素时, 不直接添加元素, 先将原容器复制生成一个新的容器, 在新的容器上添加/删除元素, 之后再用原容器指向新容器, 才用了读写分离的思想, 在迭代的过程中不需要检测fast-fail异常

但是在迭代过程中也不能检测原容器的修改,例如:

userNames的输出值不变

CopyOnWrite 对比 Vector:

CopyOnWrite:读写分离, 读和写不同的容器

Vector:读写相同的容器, 读写互斥(加锁)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值