一、Collection 接口概述
Collection是一個接口,繼承自Iterable。我們先看一下Iterable接口的源碼
package java.lang; import java.util.Iterator; import java.util.Objects; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; /** *實現這個接口的的類允許使用"for-each loop"語句來遍歷。 */ public interface Iterable<T> { /** *返回一個元素類型為T的迭代器 */ Iterator<T> iterator(); /** * jdk1.8新增的遍歷方式 */ default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } /** * 暫不研究 */ default Spliterator<T> spliterator() { return Spliterators.spliteratorUnknownSize(iterator(), 0); } }
Iterable接口有一個Iterator iterator();方法,而Collection繼承自Iterable接口,所以我們說Collection因愛與Iterator。
二、Collection 接口
Collection是一個高度封裝的集合接口,它提供了所有集合要實現的默認方法接口。
我們看一下接口源碼,了解它有哪些接口和默認實現。
package java.util; import java.util.function.Predicate; import java.util.stream.Stream; import java.util.stream.StreamSupport; /** *這是一個集合分層的根接口。集合代表了一組包含元素的對象。有些集合允許有重復的元素,有些不允許。 *有些集合是有序的有些無序的。jdk不對這個接口提供任何直接的實現,但是再一些直接子接口例如Set和List有實現了某些接口方法。 *所有繼承Collection的類必須提供兩個默認的構造函數,一個不帶參數的、一個帶Collection類型參數。 * */ public interface Collection<E> extends Iterable<E> { //查詢操作 /** *返回集合大小,也就是集合中元素的數量 */ int size(); /** * 如果集合包含元素則返回true,即判斷集合是否為空 */ boolean isEmpty(); /** * 判斷集合是否存在某個對象,注意這里參數是個Object,並沒有限制為E或其子類 */ boolean contains(Object o); /** * 返回一個迭代器iterator。並沒有說明元素的迭代順序,除非特別的集合有這個要求。 */ Iterator<E> iterator(); /** *將集合轉為對象數組,注意這里不是元素數組而是一個Object數組。 *如果集合保證是有序的,那么通過迭代器返回數組有相同順序 *返回的數組是安全的,也就是說集合有自己的引用,數組開辟新的堆內存,也有自己的引用。所以調 *用者可以隨意操作返回的數組。 *這個方法是數組和列表之間的橋梁 */ Object[] toArray(); /** * 返回一個集合元素類型的數組。如果集合滿足指定的數組並且有足夠的空間,則在其中返回此集合 * 否則返回此集合大小的新數組。 * 如果集合有序,那么返回此集合迭代器遍歷順序的數組 * 如果數組大小比集合元素多,那么在數組滿足集合元素后在末尾設置為null * * 如果在這個集合中指定數組運行時類型不是運行時元素類型的超類,那么拋ArrayStoreException異常 * 如果指定數組為空,則拋出NullPointerException */ <T> T[] toArray(T[] a); //修改操作 /** * 確保此集合包含特定的元素類型。 * 如果此集合增加元素成功返回true。 * 如果此集合不允許有重復元素並且已經包含所傳參數,那么返回false * * 支持此操作的集合可能會限制向該集合添加哪些元素。特別的,有些集合會拒絕null元素,有些 * 會對要增加的元素強加一些限制。 * Collection實現類應該在文檔中明確指出所有的限制。 * * 如果集合以除已經包含元素之外的任何原因拒絕添加特定元素,則必須拋出異常 *(而不是返回false)。這保留了集合在此調用返回后始終包含指定元素的不變式。 */ boolean add(E e); /** * 如果此集合中存在此元素,那么移除一個特定元素類型的實例。更正式的說,如果集合中包含一個或多個這樣的元素, * 那么刪除這樣的元素(o==null?e==null:o.equals(e))。如果集合包含指定的元素(或集合因調用而發生改變),那么返回true。 * * 如果指定元素的類型和集合不相容,拋出ClassCastException異常(可選的限制條件) * 如果指定元素是null並且這個集合不允許null元素存在,那么拋出NullPointerException異常(可選的限制條件) * 如果此集合不支持remove操作那么拋出UnsupportedOperationException異常(可選的限制條件) */ boolean remove(Object o); //容量操作 /** * 如果this集合包含指定集合的所有元素,返回true * c集合必須要檢查是否被包含在this集合 * 如果指定元素的類型和集合不相容,拋出ClassCastException異常(可選的限制條件) * 如果指定元素是null並且這個集合不允許null元素存在,那么拋出NullPointerException異常(可選的限制條件) */ boolean containsAll(Collection<?> c); /** * 將指定集合的所有元素到this集合中(可選的操作)。 * 如果指定的集合在操作進行時被修改了,那么此操作行為未定義。 * (這意味着如果指定的集合是這個集合,並且這個集合是非空的,那么這個調用的行為是未定義的。) * * @參數:c集合包含了要被添加到這個集合的元素 * @返回:如果調用結果改變了this集合返回true * @throws:如果 addAll操作不被此集合支持,那么拋出UnsupportedOpertaionException異常 * @throws: 如果指定集合包含了空元素而this集合不允許有空元素,那么拋出NullPointerException異常 * @throws:如果this集合阻止hiding集合元素類型添加,那么拋出ClassCastException異常 * @throws:如果指定集合的元素的某些屬性阻止將其添加到此集合,則拋出IllegalArgumentException * @throws:由於插入限制,如果不是所有元素都可以在此時添加,則拋出IllegalStateException異常 */ boolean addAll(Collection<? extends E> c); /** * 移除此集合中所有的包含在指定集合中的元素(可選的操作)。調用過此函數之后,那么此集合和指定集合將不再包含相同元素。 * * @param:包含要從該集合中刪除的元素的c集合 * @return:如果此集合因調用而更改那么返回true * @throws:如果此集合不支持removeAll方法,則拋出UnsupportedOperationException * @throws:如果集合中一個或多個元素的類型與指定集合不兼容,則拋出ClassCastException(可選的操作) * @throws:如果該集合包含一個或多個空元素,且指定的集合不支持空元素(optional),或者指定的集合為空, * 則拋出NullPointerException異常 */ boolean removeAll(Collection<?> c); /** * 移除此集合中所有符合給定Predicate的元素。在迭代期間或由Predicate引發的錯誤或運行時異常將被轉發給調用方 * @implSpec * 默認實現使用其迭代器遍歷集合的所有元素。每一個匹配的元素使用iterator.remove()來移除。 * 如果集合的iterator不支持移除將會拋出UnsupportedOperationException異常在匹匹厄到 * 第一個元素時。 * @param 過濾一個predicate * @param 篩選要刪除的元素返回true的Predicate * @return 如果任何一個元素被刪除返回true * @throws 指定過濾器為空,拋出NullPointerException * @throws 如果元素沒有被刪除,或者移除操作不支持, * 則立即拋出UnsupportedOperationException異常 * @since 1.8 */ default boolean removeIf(Predicate<? super E> filter) { //如果filter為null拋出NullPointerException Objects.requireNonNull(filter); boolean removed = false; final Iterator<E> each = iterator(); //通過迭代器遍歷刪除,只要刪除一個removed就為true while (each.hasNext()) { if (filter.test(each.next())) { each.remove(); removed = true; } } return removed; } /** * 只保留此集合中包含在指定集合中的元素(可選的操作)。 * 也就是說,此集合中不包含在指定集合中的所有元素。 * @param:要保留的元素的集合c * @return:如果此集合改變了返回true * @throws:如果此集合不支持retainAll,則拋出UnsupportedOperationException異常 * @throws:如果集合中一個或多個元素的類型與指定集合不兼容,則拋出ClassCastException(可選的操作) * @throws:如果該集合包含一個或多個空元素,且指定的集合不支持空元素(optional),或者指定的集合為空 */ boolean retainAll(Collection<?> c); /** * 移除此集合中所有元素(可選操作),調用此方法后集合里將為空。 * @throws: 如果此集合clear操作不支持將會拋出UnsupportOperationException異常。 */ void clear(); //比較和hash /** * 比較指定的對象與此集合是否相等 * */ boolean equals(Object o); /** *返回這個集合的hashCode。當集合接口沒有對Object.hashCode方法的一般協議做任何規定,編程 *人員應該注意在重寫equals方法時必須重寫hashCode方法,以便滿足一般協議對這個 *Object.hashCode方法。特別的,c1.equals(c2)表明c1.hashCode()==c2.hashCode()。 */ int hashCode(); /** *一下1.8新增的Spliterator,暫不研究 */ @Override default Spliterator<E> spliterator() { return Spliterators.spliterator(this, 0); } default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } default Stream<E> parallelStream() { return StreamSupport.stream(spliterator(), true); } }
三、AbstractCollection類
AbstractCollection是一個實現了Collection接口的抽象類,除了iterator()和size()接口,它提供了一些其他接口的默認實現,其他集合類可以繼承此類來復用。
AbstractCollection源碼
package java.util; public abstract class AbstractCollection<E> implements Collection<E> { /*唯一的構造函數*/ protected AbstractCollection(){ } //查詢操作 public abstract Iterator<E> iterator(); public abstract int size(); /* * 返回size() == 0 */ public boolean isEmpty(){ return size() == 0; } /** * 實現的contains方法,通過迭代器遍歷 */ public boolean contains(Object o){ Iterator<E> it = iterator(); 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; } /** * 此默認實現,考慮到數組在迭代器遍歷過程中大小可能會改變, * 也就是可能會增加或減少元素怒 */ public Object[] toArray(){ //估計數組大小,並做好變小或變大的准備 Object[] r = new Object[size()]; Iterator<E> it = iterator(); for (int i = 0; i < r.length; i++){ if (! it.hasNext()) //比期望的元素少,那么調用Arrays.copyOf()方法返回一個新的數組 return Arrays.copyOf(r, i); r[i] = it.next(); } //判斷集合有沒有被增加(迭代器改變),如果沒有返回數組,如果有調用finishToArray()方法返回數組 return it.hasNext() ? finishToArray(r, it) : r; } /** * */ @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; } /** * 一些VM會在數組中保留頭信息,所以要占用8字節空間,頭信息大小不能超過8 * 重新分配更大的長度給數組,如果要求的數組大小超過VM限制,會拋出OutOfMemoryError * 默認值 2147483647 - 8; */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * 重新在toArray方法中,如果iterator返回了比期望中的大小更多的元素時,重新給數組分配空間來完成填充數組。 * @param 之前的已經被填滿的數組 * @param 操作中集合的iterator * @return 除了給定的數組之外,增加了從迭代器中獲取的元素,並修正數組長度 */ @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) { //第一次(剛進來的時候)一定為true,那么分配新的數組大小 int newCap = cap + (cap >> 1) + 1; //右移一位+1再加上原大小 if (newCap - MAX_ARRAY_SIZE > 0) //新數組大小大於集合默認最大值,調用hugeCapacity()方法重新分配,值為Integer.MAX_VALUE newCap = hugeCapacity(cap + 1); r = Arrays.copyOf(r, newCap); } r[i++] = (T)it.next(); } // 修正數組多余的空間,如果正好直接返回,否則調用Arrays.copyOf()方法 return (i == r.length) ? r : Arrays.copyOf(r, i); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // 內存溢出 throw new OutOfMemoryError ("Required array size too large"); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } //修改操作 /** * 此操作總是拋出 UnsupportedOperationException * @throws UnsupportedOperationException {@inheritDoc} * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} * @throws IllegalStateException {@inheritDoc} */ public boolean add(E e) { throw new UnsupportedOperationException(); } /** * 通過集合迭代器查找元素,如果找到調用iterator.remove()方法刪除元素。 * 刪除一個就返回true */ public boolean remove(Object o) { Iterator<E> it = iterator(); if (o==null) { while (it.hasNext()) { if (it.next()==null) { it.remove(); return true; } } } else { while (it.hasNext()) { if (o.equals(it.next())) { it.remove(); return true; } } } return false; } // Bulk Operations /** * 判斷此集合是否包含指定集合所有元素,有一個沒有返回false */ public boolean containsAll(Collection<?> c) { for (Object e : c) if (!contains(e)) return false; return true; } /** * 調用add(E e)方法添加指定集合到此集合中 * * @see #add(Object) */ public boolean addAll(Collection<? extends E> c) { boolean modified = false; for (E e : c) if (add(e)) modified = true; return modified; } /** * 這個方法將從此集合中刪除指定集合的所有元素,通過迭代器刪除。 * @throws UnsupportedOperationException {@inheritDoc} * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} * * @see #remove(Object) * @see #contains(Object) */ public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); boolean modified = false; Iterator<?> it = iterator(); while (it.hasNext()) { if (c.contains(it.next())) { it.remove(); modified = true; } } return modified; } /** * 此集合中保留指定集合的所有元素,也就是說調用此方法之后,此集合中刪除了不存在指定集合中 *的元素 * */ 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; } /** * 清空集合中所有元素 * @throws UnsupportedOperationException {@inheritDoc} */ public void clear() { Iterator<E> it = iterator(); while (it.hasNext()) { it.next(); it.remove(); } } // String conversion /** * 集合的toString方法,所有繼承AbstractCollection的類都有此方法 */ public String toString() { Iterator<E> it = iterator(); if (! it.hasNext()) return "[]"; StringBuilder sb = new StringBuilder(); sb.append('['); for (;;) { E e = it.next(); //如果將自己這個集合添加到自己,就會打印(this Collection) sb.append(e == this ? "(this Collection)" : e); if (! it.hasNext()) return sb.append(']').toString(); sb.append(',').append(' '); } } } }
AbstractCollection類默認實現的方法,在上面源代碼中我都已經講解過了,很多常用的集合都會使用 默認實現,比如常用的toString方法,我們在輸出ArrayList時調用的就是此方法。
