JAVA集合源码攻坚战(12)—— AbstractSet
前言
上一篇对Set接口的方法做了个简单的介绍,主要需要注意的,就是Set是不支持重复元素,并且,无法用索引来获取对应元素。因为可以看到,声明的方法里没有根据位置信息来查找元素的。
正文
这里我们来介绍Set的一个抽象实现类AbstractSet。
java.util
Class AbstractSet<E>
java.lang.Object
java.util.AbstractCollection<E>
java.util.AbstractSet<E>
参数类型
E - 由此集合维护的元素的类型
All Implemented Interfaces:
Iterable <E>, Collection <E>, Set <E>
已知直接子类:
ConcurrentSkipListSet , CopyOnWriteArraySet , EnumSet , HashSet , TreeSet
AbstractSet比较简单,只是实现了3个方法,定义了一个无参的构造器。
实现的方法
equals方法
/**
* 实现了equals方法。比较了两个集合是否相等。
* 如果指定的对象也是set集合,并且两个set的size相等,且内部元素都一样,则返回true。
* 此定义确保equals方法在set接口的不同实现之间正常工作。
* Compares the specified object with this set for equality. Returns
* <tt>true</tt> if the given object is also a set, the two sets have
* the same size, and every member of the given set is contained in
* this set. This ensures that the <tt>equals</tt> method works
* properly across different implementations of the <tt>Set</tt>
* interface.<p>
*
*
* This implementation first checks if the specified object is this
* set; if so it returns <tt>true</tt>. Then, it checks if the
* specified object is a set whose size is identical to the size of
* this set; if not, it returns false. If so, it returns
* <tt>containsAll((Collection) o)</tt>.
*
* @param o object to be compared for equality with this set
* @return <tt>true</tt> if the specified object is equal to this set
*/
public boolean equals(Object o) {
// 先判断是否是本身
if (o == this)
return true;
// 判断是否是Set或其子类的实例对象
if (!(o instanceof Set))
return false;
Collection<?> c = (Collection<?>) o;
// 判断元素个数是否相等
if (c.size() != size())
return false;
try {
// 判断元素是否一样
return containsAll(c);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
}
hashCode方法
/**
* 返回set集合的哈希值。
* set集合的哈希值就是每个元素的哈希值的和。
* Returns the hash code value for this set. The hash code of a set is
* defined to be the sum of the hash codes of the elements in the set,
* where the hash code of a <tt>null</tt> element is defined to be zero.
* This ensures that <tt>s1.equals(s2)</tt> implies that
* <tt>s1.hashCode()==s2.hashCode()</tt> for any two sets <tt>s1</tt>
* and <tt>s2</tt>, as required by the general contract of
* {@link Object#hashCode}.
*
* <p>This implementation iterates over the set, calling the
* <tt>hashCode</tt> method on each element in the set, and adding up
* the results.
*
* @return the hash code value for this set
* @see Object#equals(Object)
* @see Set#equals(Object)
*/
public int hashCode() {
int h = 0;
Iterator<E> i = iterator();
while (i.hasNext()) {
E obj = i.next();
if (obj != null)
h += obj.hashCode();
}
return h;
}
removeAll方法
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;
}
无参构造器
/**
* 构造器
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected AbstractSet() {
}