Set接口是对数学上的Set的一种建模。和其他的集合不一样的地方是Set集合不能让其自身作为其中的元素。
Se虽然继承了Collection,但是它定义的方法在Collection里面都有。Set保存的数据是无序且不重复的元素。它没有什么特别的地方,它只是在定义Set这个概念。
Set是怎么来确定每个元素的唯一性?它要先比较2个对象的hash值是否相等,如果不等,他们就是不一样的元素,如果相等再调用他的equals方法。
在Set集合里面没有get方法,而是利用他的迭代器来访问遍历该集合。
AbstractSet实现了Set里面的部分方法。
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
if (size() > c.size()) {
for (Iterator<?> i = c.iterator(); i.hasNext(); )
modified |= remove(i.next());
} else {
for (Iterator<?> i = iterator(); i.hasNext(); ) {
if (c.contains(i.next())) {
i.remove();
modified = true;
}
}
}
return modified;
}
复制代码
上面是批量删除方法,它先比较要删除的集合的容量与该集合的容量的大小比较。
如果要批量删除的元素个数相对少,则用要删除的集合的迭代器来循环删除,这里用到了|=,他是什么意思呢?我们可以做个测试。
boolean a = false;
boolean b = true;
System.out.println(a |= false);//false
System.out.println(a |= true);//true
System.out.println(b |= false);//true
System.out.println(b |= true);//true复制代码
从上面可以看出这个操作的意思:只有当符号2边的值都是false的时候才返回false,其他情况都返回true。这正好可以用到这里。
可以看到,2种情况下的删除是有些区别的第一种情况是调用AbstractCollection里面的remove方法;第二种情况是调用的迭代器的remove方法。我们知道在删除的时候需要判断集合里面是否存在这个元素,第一种是用equals的方法(相当于contains方法的作用)来判断,但是最终也是调用的是迭代器的remove方法,本质上都是一样的。