源码注释:仅保留此列表中包含在指定集合中的元素。换句话说,从该列表中删除指定集合中不包含的所有元素。
本人解释:原数组和参数数组做交集,保留相同的部分。
源码分析部分:
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}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 : 从父类继承过来的变量,作用是记录着集合的修改次数。详情可见我另一篇博文: 请点击我
分析部分: 主要分析 batchRemove(Collection<?> c, boolean complement)方法。 complement为true
1、retainAll(Collection<?> c):原数组和参数数组做交集,保留相同的部分。
2、batchRemove(Collection<?> c, boolean complement):根据 complement 的值来制定数组移除数据策略
(1)、先分析
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];这部分
因为 complement==true。 所以,参数数组中包含原数组指定位置的数据时,就将原数组的r位置的数据覆盖掉w位置的数据,r位置的数据不变,并其w自增,r自增。 否则,r自增,w不自增
这步处理出来的数据很重要,一定要理解到,下面举个例子:
原数组: 123456789 ; 参数数组: abc358f
数组位置 012345678
循环次数 r w if值 elementData[w++]=elementData[r] 原数组值 替换位
1 0 0 false 123456789
2 1 0 false 123456789
3 2 0 true elementData[0]=elementData[2] 323456789 123456789
4 3 1 false 323456789
5 4 1 true elementData[1]=elementData[4] 353456789 323456789
6 5 2 false 353456789
7 6 2 false 353456789
8 7 2 true elementData[2]=elementData[7] 358456789 353456789
9 8 3 false 3584567899 3
这步的作用:把两个数组相同的部分前移(这步的处理尤为重要!)
(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==3,从原数组358456789 的 下标==3开始,将原数组大于下标3以后的数置null
modCount 修改的次数+3,原数组的长度修改为3。
好了 到这里就分析完了,其实我觉得难以梳理的就是分析(1)。
当然了可能有不足的地方,或者各位有更好的解释,欢迎指点指点,先谢谢了~~~