List遍历的时候删除元素的相关问题及解决方法

package com.gaopengyu;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

class Person {
    int age;
    String name;

    Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
}

//集合在遍历的时候,如果只是删除其中的一个元素,下面所有的普通for循环都是可以的,但是集合中其他元素的后续删除就不行了,因为前面的元素删除导致后续元素的位置发生了改变。
//小细节,有时候很容易就忽视了,但是有时候小细节能让你付出几个小时,甚至一天的经历来解决,遇到就记下来,下次可以快速解决。
public class RemoveWhenTraverseList {
    public static void main(String[] args) {
        Person p1 = new Person(11, "Alice");
        Person p2 = new Person(12, "Bob");
        Person p3 = new Person(13, "cindy");
        Person p4 = new Person(14, "doge");
        Person p5 = new Person(15, "ela");
        List<Person> personList = new ArrayList<Person>();
        personList.add(p1);
        personList.add(p2);
        personList.add(p3);
        personList.add(p3);
        personList.add(p4);
        personList.add(p5);
//        删除一个可以删除多个的时候可以能遗漏(两个要删除的元素相邻的情况下)
//        useOrdinaryForDelete(personList);
//        useOrdinaryForDeleteChangei(personList);
//        useOrdinaryForDeleteReverse(personList);
//        这个会报错ConcurrentModificationException。这是list集合中fail-fast机制,出现在集合遍历的时候,改变元素,就会报ConcurrentModificationException,所以利用增强for循环实现该功能是不可行的。
//        useEnhancedForDelete(personList);
        useIteratorDelete(personList);
    }

    //常规ListRemove元素时因为remove之后,后边的元素会向前补齐被删掉的位置,但是i仍然是会向前走一步的,所以会漏掉被删除的元素后边的一个元素
    public static void useOrdinaryForDelete(List<Person> personList) {
        for (int i = 0; i < personList.size(); i++) {
            if ("cindy".equals(personList.get(i).name)) {
                personList.remove(i);
            }
        }
        for (int i = 0; i < personList.size(); i++) {
            System.out.println("使用普通for循环删除多条数据之后:" + personList.get(i).name);
        }
    }

    //    第一中解决办法
    public static void useOrdinaryForDeleteChangei(List<Person> personList) {
        for (int i = 0; i < personList.size(); i++) {
            if ("cindy".equals(personList.get(i).name)) {
                personList.remove(i);
                i--;
//          在删除的同时,即list里下一个元素向前移动的同时,i跟着向前移动
            }
        }
        for (int i = 0; i < personList.size(); i++) {
            System.out.println("使用普通for循环删除多条数据同时改变i值之后:" + personList.get(i).name);
        }
    }

    //    第二中解决办法,逆序同样可以解决
    public static void useOrdinaryForDeleteReverse(List<Person> personList) {
        for (int i = personList.size() - 1; i >= 0; i--) {
            if ("cindy".equals(personList.get(i).name)) {
                personList.remove(i);
            }
        }
        for (int i = 0; i < personList.size(); i++) {
            System.out.println("使用普通for循环逆序删除多条数据之后:" + personList.get(i).name);
        }
    }

    //    使用增强for循环
    public static void useEnhancedForDelete(List<Person> personList) {
        for (Person p : personList) {
            if ("cindy".equals(p.name)) {
                personList.remove(p);
            }
        }
        for (int i = 0; i < personList.size(); i++) {
            System.out.println("使用增强for循环删除多条数据之后:" + personList.get(i).name);
        }
    }

    //    使用Iterator迭代器
    public static void useIteratorDelete(List<Person> personList) {
        Iterator<Person> it = personList.iterator();
        while (it.hasNext()) {
            if ("cindy".equals(it.next().name)) {
//                这个和上面的增强for循环一样会报错ConcurrentModificationException
//                personList.remove(it.next());
//                这个由于iterator的remove方法会同时修改expectedModCount ,所以checkformodification的时候不会出现和modcount不等导致failfast的情况。所以是正确的。
                it.remove();
            }
        }
        for (int i = 0; i < personList.size(); i++) {
            System.out.println("使用增强for循环删除多条数据之后:" + personList.get(i).name);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值