ArrayList 里的 removeAll() 及 batchRemove() 方法【可能让你感受到jdk之美的文章】

导语:removeAll(Collection<?> c) 方法不就是【从此列表中移除包含在指定集合中的所有元素】的意思吗! 这么见名之意,为啥还要讲?相信很多小伙伴儿都会有这个疑问。这样随意一个方法就写一篇文章,即浪费阅读者时间,也浪费csdn储存空间。说白了就想吐槽一句“垃圾文章!!!”。其实不然,之所以写下这篇文章,是因为 batchRemove(Collection<?> c, boolean complement) 这个方法,阅读到这个方法的源码时,瞬间让我第一次感受到jdk的美妙之处,让我从此刻起,爱上了阅读jdk源码。也许这个方法在很多人眼中很平平常,可是这是第一次让我提起了对jdk的兴趣。特此记录一番。若对你也有帮组,乃是我莫大的荣幸

先放下源码:

                 

                 transient Object[] elementData; // non-private to simplify nested class access

                 public boolean removeAll(Collection<?> c) {
                            Objects.requireNonNull(c);
                            return batchRemove(c, false);
                  }

                 private boolean batchRemove(Collection<?> c, boolean complement) {
                            final Object[] elementData = this.elementData;
                            int r = 0, w = 0;
                            boolean modified = false;
                            try {
                                for (; r < size; r++)
                                    if (c.contains(elementData[r]) == complement)
                                        elementData[w++] = elementData[r];
                            } finally {
                                // Preserve behavioral compatibility with AbstractCollection,
                                // even if c.contains() throws.

                                if (r != size) {
                                    System.arraycopy(elementData, r,
                                                     elementData, w,
                                                     size - r);
                                    w += size - r;
                                }
                                if (w != size) {
                                    // clear to let GC do its work
                                    for (int i = w; i < size; i++)
                                        elementData[i] = null;
                                    modCount += size - w;
                                    size = w;
                                    modified = true;
                                }
                            }
                            return modified;
                        }

相关字段解释:

size :原集合长度

elementData: 原集合

modCount : 从父类继承过来的变量,作用是记录着集合的修改次数。详情可见我另一篇博文: 请点击我               

分析部分:      

1、removeAll(Collection<?> c):从此列表中移除包含在指定集合中的所有元素

2、接下来看 batchRemove(Collection<?> c, boolean complement) 方法。下面我们把参数称为参数数组,调用数组称为原数组

(1)、先分析

            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];

            这部分

            因为 complement==false 。 所以,参数数组中不包含原数组指定位置的数据时,就将原数组的r位置的数据覆盖掉w位置的数据,r位置的数据不变,并其w自增,r自增。              否则,r自增,w不自增

            这步处理出来的数据很重要,一定要理解到,下面举个例子:

                原数组:     123456789   ;     参数数组:  abc358f                                                                  

                数组位置     012345678

循环次数   r   w  if值   elementData[w++]=elementData[r]    原数组值     替换位
    1          0   0  true     elementData[0]=elementData[0]         123456789   123456789
    2          1   1  true     elementData[1]=elementData[1]         123456789   123456789
    3          2   2  false                                                                 123456789  
    4          3   2  true     elementData[2]=elementData[3]         124456789   123456789
    5          4   3  false                                                                 124456789
    6          5   3  true     elementData[3]=elementData[5]         124656789   124456789
    7          6   4  true     elementData[4]=elementData[6]         124676789   124656789 
    8          7   5  false                                                                 124676789 
    9          8   5  true     elementData[5]=elementData[8]         124679789   124676789 

                9   6

   这步的作用:把需要移除的数据都替换掉,不需要移除的数据前移。(这步的处理尤为重要!)

(2)、再分析

                            if (w != size) {
                                // clear to let GC do its work
                                for (int i = w; i < size; i++)
                                    elementData[i] = null;
                                modCount += size - w;
                                size = w;
                                modified = true;
                            }

            这部分 

            跟着上面的例子,w==6,从原数组124679789的 下标==6开始,将原数组大于下标6以后的数置null
            modCount 修改的次数+3,原数组的长度修改为6。

好了 到这里就分析完了,其实我觉得难以梳理的就是分析(1)。

当然了可能有不足的地方,或者各位有更好的解释,欢迎指点指点,先谢谢了~~~

                          

猜你喜欢

转载自blog.csdn.net/weixin_40841731/article/details/85263889