ArrayList的removeAll和retainAll方法

一、含义

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;
		}
	}

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值