ArrayList使用的坑

其实这也是老生常谈的问题,但奇怪的的是最近几年在开发时都没遇到过,所以今天是个特殊的日子。

场景:比如后台返回一个列表,值可能为空,前台自己过滤

伪代码

        ArrayList<People> strings = new ArrayList<People>();
        strings.add(new People(""));
        strings.add(new People(""));
        strings.add(new People(""));
        strings.add(new People("a"));

        for (int i = 0; i < strings.size(); i++) {
            People people = strings.get(i);
            if (people.name == null || people.name == "") {
                strings.remove(people);
            }
            System.out.println(i + "----" + people.name + "------" + strings.size());
        }


0----------3
1----------2
strings.get(i)==
strings.get(i)==a

有一个符合条件的没删掉!!!

冷静下,看下源码

public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }


private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

主要是因为内部size做了-1的操作,遍历到下一节点时,index其实相当于把第二个空值跳过了直接删除了第三个。这种情况可以使用迭代器操作

  ListIterator<People> it = strings.listIterator();
        while (it.hasNext()) {
            People people = it.next();
            if (people.name == null || people.name == "") {
                it.remove();
            }
            System.out.println( people.name + "------" + strings.size());
        }

------3
------2
------1
a------1
strings.get(i)==a

顺便看看看其他坑,使用for each遍历

 for (People people : strings) {
            if (people.name == null || people.name == "") {
                strings.remove(people);
            }
            System.out.println(people.name + "------" + strings.size());
 }






Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
	at java.util.ArrayList$Itr.next(ArrayList.java:859)

报了个错,因为foreach遍历本质就是利用iterater的hasNext和next结合进行遍历 看这

iterater在创建时会把modCount赋值给expectedModCount,但增删的时候不会更新expectedModCount。

现在遇到这两种情况,应该还会有其他的,比如老版本中调用remove可能造成下标越界,因为size没有实时调整,所以有个不成文的规定,循环操作里尽量不要做remove操作,哈哈

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值