Java List数据删除

最近在公司项目中需要实现:在两个实体对象不同的列表中,删除A列表中包含B列表,通过判断A中实体和B中实体某一个属性是否相同来删除。期间出现IndexOutOfBoundsException ,ConcurrentModificationException,IllegalStateException等等异常,解决完写一篇记录下。

循序渐进,分析几个常见的遍历删除及其出错的原因:

常见错误方法一:
        List<Integer> list = new ArrayList<>();
        Collections.addAll(list, 9, 1, 3, 6, 5);

        int size = list.size();
        for (int i = 0; i < size; i++) {
            Integer value = list.get(i);
            if (value == 3 || value == 5) {
                list.remove(i);
            }
        }

此时会报IndexOutOfBoundsException 

原因:size此刻是一个常量,大小是不变的,删除了其中一个非末尾(最后一个)的元素,当遍历到最后一个元素时,索引大于了list的大小,自然就数组越界了,从中也可以看出remove方法会改变list.size()方法的大小。

常见错误方法二:
        for (Integer value : list) {
            if (value == 1 || value == 3 || value == 6) {
                list.remove(value);
            }
        }
此时会抛出 ConcurrentModificationException

原因:ArrayList中有modCountAbstractList类中的一个成员变量,expectedModCount:表示对ArrayList修改次数的期望值,它的初始值为modCount。每次remove 的时候会调用checkForComodification,检查expectedModCount是否等于modCount,如果不相等则抛出ConcurrentModificationException。而每次的remove,在fastRemove()方法中modCount都会加1,导致两个数不想等。此刻不禁会有疑问,为什么remove(index) 抛的是IndexOutOfBoundsException,而remove(Object)抛的却是ConcurrentModificationException?难道remove(index)没有调用checkForComodification,期待大神解答。

常见错误方法三:

for (int i = 0; i < list.size(); i++) {
    Integer value = list.get(i);

    if (value == 1 || value == 3 || value == 6) {
        list.remove(i);
        System.out.println(value);
    }
}

此时没有抛异常,但是不能实现我们需要的功能,我们想删除1,3,6,但是结果呈现的是只删除了1和6。为什么会出现这种情况呐?

原因:1的索引为2,当删除了1后,list的长度变化,3变到1的位置,而1删除后索引还是加1,导致3成了落网之鱼,而6的索引是2,所以当索引加到2时,6也就被删除了。

单列表操作正确方法一:
 for (int i = 0; i < list.size(); i++) {
            Integer value = list.get(i);

            if (value == 1 || value == 3 || value == 6) {
                list.remove(i);
                i--;
                System.out.println(value);
            }
        }

单列表操作正确方法二:

        for (int i = list.size() - 1; i >= 0; i--) {
            Integer value = list.get(i);
            if (value == 1 || value == 3 || value == 6) {
                list.remove(i);
                System.out.println(value);

            }
        }

单列表操作正确方法三(推荐):

        Iterator<Integer> it = list.iterator();

        while (it.hasNext()) {
            Integer value = it.next();
            if (value == 1 || value == 3 || value == 6) {
                System.out.println(value);
                it.remove();
            }
        }

双列表去重操作方法一(推荐):












































猜你喜欢

转载自blog.csdn.net/u012977315/article/details/80608724
今日推荐