寫在前面
自開始在公司實習(xí)以來,經(jīng)常都要用到集合框架。不僅后臺要用,在前臺做數(shù)據(jù)交互的時候用得也多。所以我想著是時候深入地學(xué)習(xí)一下Java的集合框架,搞搞它們的源碼了。
下面先把Java集合框架的結(jié)構(gòu)圖放出來(摘自《Thinking in Java》):
其實呢,把上面的圖提煉一下,Java集合框架的簡略UML類圖如下:
- Collection接口簡要類圖:
- Map接口簡要類圖:
PS:上面兩個UML圖真的畫得非常非常簡略,其實Collection和Map接口下面還有很多的子接口以及實現(xiàn)類,具體有哪些可以參照官方文檔
Collection接口介紹
Collection接口繼承自超級接口Iterator,是Collection層次結(jié)構(gòu)中的根接口。Collection表示一組對象,這些對象也被稱為Collection的元素。一些Collection允許有重復(fù)的元素(例如List),但是另一些則不允許有重復(fù)的元素,即可為無序的(如Set)。JDK不提供此接口的任何直接實現(xiàn)---它會提供更為具體的子接口(如Set和List),這從上面的UML也可以看出來。此接口用來傳遞Collection,并在需要最大普遍性的地方操作這些Collection。
- 關(guān)于構(gòu)造方法
所有通用的Collection實現(xiàn)類(通常通過它的一個子接口間接實現(xiàn)Collection)應(yīng)該提供兩個"標(biāo)準(zhǔn)"構(gòu)造方法:一個是使用void聲明的構(gòu)造方法,用于創(chuàng)建空Collection;另一個是帶有Collection類型單參數(shù)的構(gòu)造方法,用于創(chuàng)建一個具有與其參數(shù)相同元素的新的Collection。實際上,后者允許用戶復(fù)制任何Collection,以生產(chǎn)所需實現(xiàn)類型的一個等效Collection。盡管無法強(qiáng)制執(zhí)行此約定(因為接口不能包含構(gòu)造方法),但是Java平臺庫中所有通用的Collection實現(xiàn)都遵從它。
為了驗證是否如上所說的,我打開了ArrayList的源碼來研究一下:
首先可以看到一個使用void聲明的無參構(gòu)造方法:
然后我們還看到了一個參數(shù)類型為Collection的構(gòu)造方法:
由此可以看出上面那段話對于構(gòu)造方法的描述是正確的。至于構(gòu)造方法內(nèi)部具體是如何實現(xiàn)的,等以后我再慢慢開博客來介紹。
- 關(guān)于破壞性方法
Collection接口中包含某些破壞性方法。破壞性方法,是指可以修改其所操作的Collection的那些方法。比如說某個破壞性方法的參數(shù)類型為Collection,即可以往里面?zhèn)饕粋€Collection實例,如果此方法可以修改這個Collection實例,那么它就是破壞性方法。如果這個被傳入的collection不支持該操作,則指定這些方法拋出UnSupportedOperationException。如果是這樣,那么在調(diào)用對該collection無效的時候,這些方法可能但不一定拋出UnSupportedOperationException。例如,如果要添加的collection為空并且不可修改,則在對該collection調(diào)用addAll(Collection)方法時,可能但不一定會拋出異常。
- 關(guān)于一些限制
一些collection實現(xiàn)對它們可能包含的元素有所限制。例如,某些實現(xiàn)禁止Null元素,而某些實現(xiàn)則對元素的類型有所限制。試圖添加不合法的元素將拋出一個未經(jīng)檢查的異常,一般來說是NullPointerException或者是ClassCastException。試圖查詢是否存在不合格的元素也可能拋出一個異常,或者只是簡單地返回false;某些不適合的實現(xiàn)將表現(xiàn)出前一種行為,即拋出一個異常,而某些實現(xiàn)則表現(xiàn)出后一種行為。較為常見的是,試圖對某個不合法的元素執(zhí)行操作且該操作的完成不會導(dǎo)致將不合法的元素插入collection中,將可能拋出一個異常,也可能操作成功。這取決于實現(xiàn)本身。這樣的異常再次接口的規(guī)范中標(biāo)記為"可選"
- 關(guān)于同步策略
這主要是由每個collection來確定自身的同步策略。在沒有事先的強(qiáng)烈保證的情況之下,調(diào)用由另一進(jìn)程正在更改的collection的方法可能會出現(xiàn)不確定行為;這包括直接調(diào)用,將collection傳遞給可能執(zhí)行調(diào)用的方法,以及使用現(xiàn)有迭代器檢查collection。
- 其它
Collections Frameword接口中的很多方法是根據(jù)equals方法定義的。例如,contain(Object o )方法的閨房聲明:“當(dāng)且僅當(dāng)此collection包含至少一個滿足(o == null ? e == null : o.equals(e))的元素e時,返回true。”不應(yīng)將此規(guī)范理解為它暗指調(diào)用具有非空參數(shù)o的Collection.contains方法會導(dǎo)致任意的e元素調(diào)用o.equals(e)方法。可隨意對各種實現(xiàn)執(zhí)行優(yōu)化,只要避免調(diào)用equals即可。例如,通過首先比較兩個元素的哈希碼(Object.hashCode()規(guī)范保證哈希碼不相等的兩個對象不會相等)。較為常見的是,各種Collections FrameWord接口的實現(xiàn)課隨意利用底層Object方法的指定
Collection接口方法摘要:
偷個懶,直接把JDK文檔里面的搬過來
方法詳細(xì)信息:
size
int size()
返回此collection中的元素的數(shù)量。如果此collection包含的元素數(shù)量大于 Integer.MAX_VALUE,則返回Integer.MAX_VALUE。
返回:此collection中元素的數(shù)量
isEmpty
boolean isEmpty()
如果此collection不包含元素,則返回true。
返回:如果此collection不包含元素,則返回true
contains
boolean contains(Object o)
如果此collection包含指定的元素,則返回true。更確切地說,當(dāng)且僅當(dāng)此collection至少包含一個滿足(o == null ? e == null :o. equals(e))的元素e時,返回true。
參數(shù): o - 測試在此collection中是否存在的元素。
返回: 如果此collection包含指定的元素,則返回true。
拋出:
ClassCastException:如果指定元素的類型與此collection不兼容(可選)
NullPointerException:如果指定的元素為null,并且此collection不允許null元素(可選)
iterator
Iterator<E> iterator()
返回在此collection的元素上進(jìn)行迭代的迭代器。關(guān)于元素返回的順序沒有任何保證,除非此collection是某個能提供保證順序的類的實例。
制定者:接口Iterator<E>中的iterator
返回:在此collection的元素上進(jìn)行迭代的Iterator
toArray
Object[] toArray()
返回包含此collection中所有元素的數(shù)組。如果collection對其迭代器返回的元素順序做出了某些保證,那么此方法必須以相同的順序返回這些元素。
返回的數(shù)組將是“安全地”,因此此collection并不維護(hù)對返回數(shù)組的任何引用。換句話說,即使collection受到數(shù)組的支持,此方法也必須分配一個新的數(shù)組,因此,調(diào)用者可以隨意修改返回的數(shù)組。
此方法充當(dāng)了基于數(shù)組的API與基于collection的API之間的橋梁。
返回:包含此collection中所有元素的數(shù)組
toArray
<T> T[] toArray(T[] a)
返回包含此 collection 中所有元素的數(shù)組;返回數(shù)組的運行時類型與指定數(shù)組的運行時類型相同。如果指定的數(shù)組能容納該 collection,則返回包含此 collection 元素的數(shù)組。否則,將分配一個具有指定數(shù)組的運行時類型和此 collection 大小的新數(shù)組。
如果指定的數(shù)組能容納 collection,并有剩余空間(即數(shù)組的元素比 collection 的元素多),那么會將數(shù)組中緊接 collection 尾部的元素設(shè)置為 null。(只有 在調(diào)用者知道此 collection 沒有包含任何 null
元素時才能用此方法確定 collection 的長度。)
如果此 collection 對其迭代器返回的元素順序做出了某些保證,那么此方法必須以相同的順序返回這些元素。
像 toArray() 方法一樣,此方法充當(dāng)基于數(shù)組的 API 與基于 collection 的 API 之間的橋梁。更進(jìn)一步說,此方法允許對輸出數(shù)組的運行時類型進(jìn)行精確控制,并且在某些情況下,可以用來節(jié)省分配開銷。
假定 x是只包含字符串的一個已知 collection。以下代碼用來將 collection 轉(zhuǎn)儲到一個新分配的 String數(shù)組:
String[] y = x.toArray(new String[0]);
注意,toArray(new Object[0])
和 toArray()
在功能上是相同的。
參數(shù):
a
- 存儲此 collection 元素的數(shù)組(如果其足夠大);否則,將為此分配一個具有相同運行時類型的新數(shù)組。
返回:
包含此 collection 中所有元素的數(shù)組
拋出:
ArrayStoreException- - 如果指定數(shù)組的運行時類型不是此 collection 每個元素運行時類型的超類型
NullPointerException - 如果指定的數(shù)組為 null
add
boolean add(E e)
確保此 collection 包含指定的元素(可選操作)。如果此 collection 由于調(diào)用而發(fā)生更改,則返回 true
。(如果此 collection 不允許有重復(fù)元素,并且已經(jīng)包含了指定的元素,則返回 false
。)支持此操作的 collection 可以限制哪些元素能添加到此 collection 中來。需要特別指出的是,一些 collection 拒絕添加 null
元素,其他一些 collection 將對可以添加的元素類型強(qiáng)加限制。Collection 類應(yīng)該在其文檔中清楚地指定能添加哪些元素方面的所有限制。
如果 collection 由于某些原因(已經(jīng)包含該元素的原因除外)拒絕添加特定的元素,那么它必須 拋出一個異常(而不是返回 false
)。這確保了在此調(diào)用返回后,collection 總是包含指定的元素。
參數(shù):
e
- 確定此 collection 中是否存在的元素。
返回:
如果此 collection 由于調(diào)用而發(fā)生更改,則返回true
拋出:
UnsupportedOperationException
- 如果此 collection 不支持 add
操作
ClassCastException - 如果指定元素的類不允許它添加到此 collection 中
NullPointerException - 如果指定的元素為 null,并且此 collection 不允許 null 元素
IllegalArgumentException - 如果元素的某屬性不允許它添加到此 collection 中
IllegalStateException - 如果由于插入限制,元素不能在此時間添加
remove
boolean remove(Object o )
從此 collection 中移除指定元素的單個實例,如果存在的話(可選操作)。更確切地講,如果此 collection 包含一個或多個滿足 (o==null ? e==null : o.equals(e))
的元素 e
,則移除這樣的元素。如果此 collection 包含指定的元素(或者此 collection 由于調(diào)用而發(fā)生更改),則返回 true
。
參數(shù):
o
- 要從此 collection 中移除的元素(如果存在)。
返回:
如果此調(diào)用將移除一個元素,則返回 true
拋出:
ClassCastException
- 如果指定元素的類型與此 collection 不兼容(可選)
NullPointerException - 如果指定的元素為 null,并且此 collection 不允許 null 元素(可選)。
UnsupportedOperationException - 如果此 collection 不支持 remove
操作
containsAll
boolean containsAll(Collection<?> c)
如果此 collection 包含指定 collection 中的所有元素,則返回 true
。
參數(shù):
c
- 將檢查是否包含在此 collection 中的 collection
返回:
如果此 collection 包含指定 collection 中的所有元素,則返回 true
拋出:
ClassCastException
- 如果指定 collection 中有一個或多個元素的類型與此 collection 不兼容(可選)
NullPointerException - 如果指定 collection 包含一個或多個 null 元素,并且此 collection 不允許 null 元素(可選),或者指定的 collection 為 null
addAll
boolean addAll(Collection<? extends E> c)
將指定 collection 中的所有元素都添加到此 collection 中(可選操作)。如果在進(jìn)行此操作的同時修改指定的 collection,那么此操作行為是不確定的。(這意味著如果指定的 collection 是此 collection,并且此 collection 為非空,那么此調(diào)用的行為是不確定的。)
參數(shù):
c
- 包含要添加到此 collection 的元素的 collection
返回:
如果此 collection 由于調(diào)用而發(fā)生更改,則返回true
拋出:
UnsupportedOperationException
- 如果此 collection 不支持 addAll
方法
ClassCastException - 如果指定 collection 中某個元素的類不允許它添加到此 collection 中
NullPointerException - 如果指定 collection 包含 null 元素,并且此 collection 不支持 null 元素,或者指定的 collection 為 null
IllegalArgumentException
- 如果指定 collection 的元素的某屬性不允許它添加到此 collection 中
IllegalStateException - 如果由于插入限制,不是所有的元素都能在此時間添加
removeAll
boolean removeAll(Collection<?> c)
移除此 collection 中那些也包含在指定 collection 中的所有元素(可選操作)。此調(diào)用返回后,collection 中將不包含任何與指定 collection 相同的元素。
參數(shù):
c
- 辦好要從此 collection 移除的元素的 collection
返回:
如果此 collection 由于調(diào)用而發(fā)生更改,則返回true
拋出:
UnsupportedOperationException
- 如果此 collection 不支持 removeAll
方法
ClassCastException - 如果此 collection 中一個或多個元素的類型與指定 collection 不兼容(可選)
NullPointerException - 如果此 collection 包含一個或多個 null 元素,并且指定的 collection 不支持 null 元素(可選),或者指定的 collection 為 null
retainAll
boolean retainAll(Collection<?> c)
僅保留此 collection 中那些也包含在指定 collection 的元素(可選操作)。換句話說,移除此 collection 中未包含在指定 collection 中的所有元素。
參數(shù):
c
- 包含保留在此 collection 中的元素的 collection
返回:
如果此 collection 由于調(diào)用而發(fā)生更改,則返回true
拋出:
UnsupportedOperationException
- 如果此 collection 不支持 retainAll
操作
ClassCastException - 如果此 collection 中一個或多個元素的類型與指定 collection 不兼容(可選)
NullPointerException - 如果此 collection 包含一個或多個 null 元素,并且指定的 collection 不允許 null 元素(可選),或者指定的 collection 為null
clear
void clear()
移除此 collection 中的所有元素(可選操作)。此方法返回后,除非拋出一個異常。
拋出:
UnsupportedOperationException
- 如果此 collection 不支持 clear
操作
equals
boolean equals(Object o )
比較此 collection 與指定對象是否相等。當(dāng) Collection
接口沒有對 Object.equals
的常規(guī)協(xié)定添加任何約定時,“直接”實現(xiàn)該 Collection
接口(換句話說,創(chuàng)建一個 Collection
,但它不是 Set
或 List
的類)的程序員選擇重寫 Object.equals
方法時必須小心。沒必要這樣做,最簡單的方案是依靠 Object
的實現(xiàn),然而實現(xiàn)者可能希望實現(xiàn)“值比較”,而不是默認(rèn)的“引用比較”。(List
和 Set
接口要求進(jìn)行這樣的值比較。)
Object.equals
方法的常規(guī)協(xié)定聲稱相等必須是對稱的(換句話說,當(dāng)且僅當(dāng)存在 b.equals(a)
時,才存在a.equals(b)
)。List.equals
和 Set.equals
的協(xié)定聲稱列表只能與列表相等,set 只能與 set 相等。因此,對于一個既不實現(xiàn) List
又不實現(xiàn) Set
接口的 collection 類,當(dāng)將此 collection 與任何列表或 set 進(jìn)行比較時,常規(guī)的equals
方法必須返回 false
。(按照相同的邏輯,不可能編寫一個同時正確實現(xiàn) Set
和 List
接口的類。)
覆蓋:
類 Object
中的 equals
參數(shù):
o
- 要與此 collection 進(jìn)行相等性比較的對象。
返回:
如果指定對象與此 collection 相等,則返回 true
hashCode
int hashCode()
返回此 collection 的哈希碼值。當(dāng) Collection
接口沒有為 Object.hashCode
方法的常規(guī)協(xié)定添加任何約束時,為了滿足 Object.hashCode
方法的常規(guī)協(xié)定,程序員應(yīng)該注意任何重寫 Object.equals
方法的類必須重寫 Object.hashCode
方法。需要特別指出的是,c1.equals(c2)
暗示著c1.hashCode()==c2.hashCode()
。
覆蓋:
類 Object
中的 hashCode
返回:
此 collection 的哈希碼值
以上是Collection接口的概述,以后再慢慢用代碼對其中的方法進(jìn)行驗證。