一、含义
1、removeAll方法 从list中删除指定集合中包含的所有元素
2、retainAll方法 从list中删除指定集合中不包含的所有元素
二、源码:
1、removeAll源码
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);//判断参数是否为空
return batchRemove(c, false);//删除指定集合中包含的所有元素
}
2、retainAll源码
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);//判断参数是否为空
return batchRemove(c, true);//删除指定集合中不包含的所有元素
}
判断参数是否为空的方法暂不考虑,两个方法都调用了batchRemove方法,只是第二个参数传递不同,一个是false一个是true
3、batchRemove源码
//用removeAll方法说明(complement = false)
private boolean batchRemove(Collection<?> c, boolean complement) {
//elementData是arraylist中存储数据的数组
final Object[] elementData = this.elementData;
//r控制循环、w控制elementData的下表
int r = 0, w = 0;
boolean modified = false;
try {
//举例说明for循环
//原数组elementData中的数据["a","b","c","d","e"]
//参数的Collection假设为arraylist,数组是["b","c","d"]
//for循环第一轮 r=0,w=0判读语句(c.contains(elementData[r]) == complement)为true
//进入if的代码块 elementData[w++] = elementData[r];
//也就是elementData[0] = elementData[0] 即elementData[0]=a; w自增
//for循环第二轮 r=1,w=1判读语句(c.contains(elementData[r]) == complement)为false
//for循环第三轮 r=2,w=1判读语句(c.contains(elementData[r]) == complement)为false
//for循环第四轮 r=3,w=1判读语句(c.contains(elementData[r]) == complement)为false
//for循环第五轮 r=4,w=1判读语句(c.contains(elementData[r]) == complement)为true
//进入if的代码块 elementData[w++] = elementData[r];
//也就是elementData[1] = elementData[4] 即elementData[1]=e; w自增
//循环完成后elementData中的数据["a","e","c","d","e"](注意第二个元素) r=5 w=2
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
//如果contains方法使用过程报异常,将剩下的元素都赋值给集合elementData
if (r != size) {
System.arraycopy(elementData, r, elementData, w, size - r);
w += size - r;
}
//将elementData[w]之后的数据置空
if (w != size) {
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
//完成后elementData中的数据["a","e",null,null,null]
}
return modified;
}
4、在batchRemove方法中的判断语句if (c.contains(elementData[r]) == complement)中的contains方法
//以arraylist为例
public boolean contains(Object o) {
//调用了indexOf方法
return indexOf(o) >= 0;
}
5、在contains方法中调用了indexOf方法
//以arraylist为例
public int indexOf(Object o) {
//null的情况暂不考虑
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
//循环调用,利用equals方法判断是否存在
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
三、总结
1、removeAll或者retainAll方法调用private方法batchRemove。
2、batchRemove方法中有个判断语句调用了contains方法。
3、contains方法中调用了indexOf方法。
4、indexOf方法中调用equals方法。
ArrayList<String> list1 = new ArrayList<String>();
list1.add("a");
list1.add("b");
list1.add("c");
list1.add("d");
list1.add("e");
ArrayList<String> list2 = new ArrayList<String>();
list2.add("b");
list2.add("c");
list2.add("d");
list1.removeAll(list2);
for(String s : list1) {
System.out.println(s);
}
上面的代码段可以得到预期的效果 输出 a e
ArrayList<Person> personList1 = new ArrayList<Person>();
ArrayList<Person> personList2 = new ArrayList<Person>();
Person persona = new Person("a", 18);
Person personb = new Person("b", 19);
Person personc = new Person("c", 20);
Person persond = new Person("d", 21);
Person persone = new Person("e", 22);
Person personf = new Person("b", 19);
Person persong = new Person("c", 20);
Person personh = new Person("d", 21);
personList1.add(persona);
personList1.add(personb);
personList1.add(personc);
personList1.add(persond);
personList1.add(persone);
personList2.add(personf);
personList2.add(persong);
personList2.add(personh);
personList1.removeAll(personList2);
for(Person p : personList1) {
System.out.println(p.getName());
}
上面的代码段如果要用personList1.removeAll(personList2);得到预期的效果需要重写Person类的equals方法
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//重写equals方法后 arraylist的removeAll方法能够得到预期的效果
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Person) {
Person p = (Person) obj;
if (this.name.equals(p.getName()) && this.age == p.getAge()) {
return true;
} else {
return false;
}
} else {
return false;
}
}
}