jdk1.8.0_45源碼解讀——Set接口和AbstractSet抽象類的實現
一、 Set架構

如上圖:
(01) Set 是繼承於Collection的接口。它是一個不允許有重復元素的集合。
(02) AbstractSet 是一個抽象類,它繼承於AbstractCollection。AbstractCollection實現了Set中的絕大部分函數,為Set的實現類提供了便利。
(03) HastSet 和 TreeSet 是Set的兩個實現類。
HashSet依賴於HashMap,它實際上是通過HashMap實現的。HashSet中的元素是無序的。
TreeSet依賴於TreeMap,它實際上是通過TreeMap實現的。TreeSet中的元素是有序的。
(04) LinkedHashSet繼承於HashSet,是具有可預知迭代順序的 Set 接口的哈希表和鏈接列表實現。此實現與 HashSet 的不同之外在於,后者維護着一個運行於所有條目的雙重鏈接列表。此鏈接列表定義了迭代順序,即按照將元素插入到 set 中的順序(插入順序)進行迭代。
二、 Set接口
一個不包含重復元素的 collection。更確切地講,set 不包含滿足 e1.equals(e2) 的元素對 e1 和 e2,並且最多包含一個 null 元素。正如其名稱所暗示的,此接口模仿了數學上的 set 抽象。
注:如果將可變對象用作 set 元素,那么必須極其小心。如果對象是 set 中某個元素,以一種影響 equals 比較的方式改變對象的值,那么 set 的行為就是不確定的。此項禁止的一個特殊情況是不允許某個 set 包含其自身作為元素。
public interface Set<E> extends Collection<E> { // Query Operations int size(); boolean isEmpty(); boolean contains(Object o); Iterator<E> iterator(); Object[] toArray(); //返回一個包含set中所有元素的數組 <T> T[] toArray(T[] a); //返回一個包含此set中所有元素的數組;返回數組的運行時類型是指定數組的類型 // Modification Operations boolean add(E e); boolean remove(Object o); // Bulk Operations boolean containsAll(Collection<?> c); //如果此set包含指定 collection 的所有元素,則返回 true boolean addAll(Collection<? extends E> c); boolean retainAll(Collection<?> c); //僅保留set中那些包含在指定 collection中的元素 boolean removeAll(Collection<?> c); //移除set中那些包含在指定 collection中的元素 void clear(); // Comparison and hashing boolean equals(Object o); int hashCode(); //返回set的哈希碼 }
三、AbstractCollection抽象類此類提供 Collection 接口的骨干實現,以最大限度地減少了實現此接口所需的工作。繼承此抽象類的直接已知子類有:AbstractList,AbstractQueue,AbstractSet,ArrayDeque。
要實現一個不可修改的collection,編程人員只需擴展此類,並提供iterator()和 size()方法的實現,其中iterator()方法返回的迭代器必須實現 hasNext()和 next()。
要實現可修改的collection,編程人員必須另外重寫此類的add()方法,否則,會拋出 UnsupportedOperationException),iterator()方法返回的迭代器還必須另外實現其 remove()方法。
public abstract class AbstractCollection<E> implements Collection<E> { protected AbstractCollection() { } public abstract Iterator<E> iterator(); public abstract int size(); public boolean isEmpty() { return size() == 0; } public boolean contains(Object o) { Iterator<E> it = iterator(); //集合中可以含有null值 if (o==null) { while (it.hasNext()) if (it.next()==null) return true; } else { while (it.hasNext()) if (o.equals(it.next())) return true; } return false; } //返回包含此 collection中所有元素的數組。 public Object[] toArray() { // Estimate size of array; be prepared to see more or fewer elements Object[] r = new Object[size()]; Iterator<E> it = iterator(); for (int i = 0; i < r.length; i++) { if (! it.hasNext()) // fewer elements than expected return Arrays.copyOf(r, i); //返回一個長度為i的數組,元素為r中相應的值 r[i] = it.next(); } //finishToArray(r, it) ensures more elements than expected //r數組已經填滿了所有的元素,但如果迭代器中仍有元素,則通過finishToArray(r, it)來重新調整 return it.hasNext() ? finishToArray(r, it) : r; } //返回包含此 collection 中所有元素的數組;返回數組的運行時類型與指定數組的運行時類型相同 @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { // Estimate size of array; be prepared to see more or fewer elements int size = size(); T[] r = a.length >= size ? a : (T[])java.lang.reflect.Array .newInstance(a.getClass().getComponentType(), size); Iterator<E> it = iterator(); for (int i = 0; i < r.length; i++) { if (! it.hasNext()) { // fewer elements than expected if (a == r) { r[i] = null; // null-terminate } else if (a.length < i) { return Arrays.copyOf(r, i); } else { System.arraycopy(r, 0, a, 0, i); if (a.length > i) { a[i] = null; } } return a; } r[i] = (T)it.next(); } // more elements than expected return it.hasNext() ? finishToArray(r, it) : r; } //可分配給數組的最大長度 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * 在toArray()方法中,如果迭代器中比預料中有更多的元素時,用已經存滿的數組和迭代器完成toArray的填充工作 * * @param r 已經存滿元素的數組 * @param it collection的正在處理的迭代器 * @return 返回包含給定數組r中的所有元素和迭代器it返回的所有元素的數組 */ @SuppressWarnings("unchecked") private static <T> T[] finishToArray(T[] r, Iterator<?> it) { int i = r.length; while (it.hasNext()) { //迭代器 int cap = r.length; if (i == cap) { int newCap = cap + (cap >> 1) + 1; //新數組擴容1.5倍 // overflow-conscious code if (newCap - MAX_ARRAY_SIZE > 0) newCap = hugeCapacity(cap + 1); r = Arrays.copyOf(r, newCap); //返回一個長度為newCap,元素包含r中所有元素的數組 } r[i++] = (T)it.next(); //將迭代器中返回的元素逐個放入數組中 } // trim if overallocated return (i == r.length) ? r : Arrays.copyOf(r, i); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError ("Required array size too large"); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } // Modification Operations public boolean add(E e) { throw new UnsupportedOperationException(); } //從此 collection中移除指定的元素 //注意如果iterator()方法返回的迭代器沒有實現remove()方法,則在刪除指定元素時會報UnsupportedOperationException public boolean remove(Object o) { Iterator<E> it = iterator(); // if (o==null) { while (it.hasNext()) { if (it.next()==null) { it.remove(); //利用迭代器實現的remove()方法進行元素刪除 return true; } } } else { while (it.hasNext()) { if (o.equals(it.next())) { it.remove(); return true; } } } return false; } //如果此 collection 包含指定 collection 中的所有元素,則返回 true public boolean containsAll(Collection<?> c) { for (Object e : c) if (!contains(e)) return false; return true; } //將指定 collection 中的所有元素都添加到此 collection中 public boolean addAll(Collection<? extends E> c) { boolean modified = false; for (E e : c) if (add(e)) modified = true; return modified; } //移除此 collection 中那些也包含在指定 collection中的所有元素 public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); //檢查給定的對象引用是否為null,若是,拋出NullPointerException boolean modified = false; Iterator<?> it = iterator(); while (it.hasNext()) { if (c.contains(it.next())) { //如果給定的集合中包含該元素,則刪除 it.remove(); modified = true; } } return modified; } //僅保留此 collection 中那些也包含在指定 collection的元素,和removeAll(Collection<?> c)正好相反 public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); boolean modified = false; Iterator<E> it = iterator(); while (it.hasNext()) { if (!c.contains(it.next())) { //如果給定的集合中不包含該元素,則刪除 it.remove(); modified = true; } } return modified; } //移除此 collection中的所有元素 public void clear() { Iterator<E> it = iterator(); while (it.hasNext()) { it.next(); it.remove(); } } //返回此 collection 的字符串表示形式:[e1, e2, ...] public String toString() { Iterator<E> it = iterator(); if (! it.hasNext()) return "[]"; StringBuilder sb = new StringBuilder(); sb.append('['); for (;;) { E e = it.next(); sb.append(e == this ? "(this Collection)" : e); if (! it.hasNext()) return sb.append(']').toString(); sb.append(',').append(' '); } } }
四、AbstractSet抽象類
此類提供 Set 接口的骨干實現,從而最大限度地減少了實現此接口所需的工作。
注意,此類並沒有重寫 AbstractCollection 類中的任何實現(包括add()方法)。它僅僅添加了 equals 和 hashCode 的實現。
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> { protected AbstractSet() { } // 比較指定對象與此 set的相等性,如果指定的對象也是一個set,並且兩個set有相同的大小,元素,則返回true。 public boolean equals(Object o) { if (o == this) return true; //1.先檢查指定的對象是不是set if (!(o instanceof Set)) return false; Collection<?> c = (Collection<?>) o; //2.再檢查指定set的大小與這個set的大小是否相等 if (c.size() != size()) return false; try { //3.最后檢查這個set是否包含指定set中的所有元素 return containsAll(c); } catch (ClassCastException unused) { return false; } catch (NullPointerException unused) { return false; } } //返回此set的哈希碼值:即該set中所有元素的哈希值之和 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; } //從此 set中移除包含在指定 collection中的所有元素 public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); boolean modified = false; //如果此set的大小>指定集合c的大小 if (size() > c.size()) { //迭代指定集合c中的元素,並在此set中逐個刪除 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; } }
