Collection是一個接口,繼承自Iterable。我們先看一下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拋出NullPointerExceptionObjects.requireNonNull(filter);boolean removed = false;final Iterator<E> each = iterator();//通過迭代器遍歷刪除,只要刪除一個removed就為truewhile (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,暫不研究*/@Overridedefault 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()接口,它提供了一些其他接口的默認實現,其他集合類可以繼承此類來復用。
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 elementsint 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 expectedif (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 expectedreturn 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_VALUEnewCap = 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時調用的就是此方法。