Java集合删除元素ArrayList实例解析

AbstractCollection集合类中有一个remove方法,该方法为了适配多种不同的集合,允许删除空的元素,看这部分代码的时候产生了疑问,为什么这里直接用it.remove()就直接删除了?   

如果有想学习java的同学,可来我们的java技术学习QQ群:165080868,免费送整套系统的java视频教程!我每晚上8点还会在群内直播讲解Java知识,欢迎大家前来学习哦。

public boolean remove(Object o) {

        Iterator<E> it = iterator();

        if (o==null) {

            while (it.hasNext()) {

                if (it.next()==null) {

                    it.remove();

                    return true;

                }

            }

        } else {

            while (it.hasNext()) {

                if (o.equals(it.next())) {

                    it.remove();

                    return true;

                }

            }

        }

        return false;

    }

接下来,拿ArrayList为例子,进行说明。其继承结构如下图所示。并且,ArrayList内部有其使用的Iterator的实现类。 


编写一段测试代码:

AbstractCollection<String> list = new ArrayList<>();
        list.add("a");
        list.add(null);
        list.add(null);

        Iterator<String> iter = list.iterator();
        while(iter.hasNext()) {
            if(iter.next() == null) {
                iter.remove();
            }
        }
        System.out.println(list);

关键点还是在于iter.next() == null 这一行,next的源码如下:

    public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

cusor在这里表示的是遍历时的索引,在调用next方法的时候其实cusor已经指向了当前元素的下一个元素,而使用lasrRet来获取当前的索引上的数据并将其返回。

而remove()方法中是通过lastRet的索引进行删除的。     

   public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

借助上文中提到的测试实例,可以进行每一步的推算。 
1. 调用next()方法,cursor指向0号元素,i被赋值为cursor的值,然后cursor被修改为i+1,指向了1号元素,也就是null所在的位置, lastRet被赋值为0。 
2. 调用next()方法,cursor指向了1号元素,赋值给i,然后cursor又通过i+1递增变为2,lastRet被赋值为1 
3. 执行删除,删除该集合lastRet上所代表的元素。删除完成后修改cursor指针同时使得expectedModCount和modCount保持一致避免fastfail。

欢迎关注程序员白胖胖,可视化学习java,每天更新文章,让Java学习更加简单。

声明:本文内容来源于网络,如有侵权请联系删除

猜你喜欢

转载自blog.csdn.net/tanzhouxiaomanxi/article/details/89149122