导语: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 1246767899 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)。
当然了可能有不足的地方,或者各位有更好的解释,欢迎指点指点,先谢谢了~~~