集合家族

Collection接口
Collection接口Api一覽

由圖中我們可以看出:
- 重寫了Iterable接口的iterator方法。
- 重寫了Object類的equals和hashCode方法。
- 定義了一系列待實現(xiàn)方法。
為什么重寫Iterable接口的iterator方法

很直觀。我們一看注釋其實就能大概明白Java設計人員的思路,其實Iterable接口可以看成許多容器類共同特性被提取出來做了接口。而相對于不同容器,這個共有特性的具體實現(xiàn)細節(jié)又不同。既然不同所以又要自己定義自己系列的迭代器規(guī)則,并讓所有實現(xiàn)類都遵循這個規(guī)則。
對于Collection接口來說,它規(guī)定子接口及其實現(xiàn)類都必須滿足它重新設定的規(guī)則。
Returns an iterator over the elements in this collection. There are no guarantees concerning the order in which the elements are returned
針對于集合中的所有元素返回一個該集合的迭代器。 但是該迭代器無法保證元素間具有順序性。(除非這個集合是某個具有這一特性的類的實例)
Collection Api 詳解
這里大家可以看Api文檔,講的比我自己理解的好很多。這里我只是想順便鍛煉一下自己看英文文獻的能力。并且很多不懂的我都是照搬了Api文檔
boolean add(E e)
向集合中添加一個元素。集合更改則添加成功返回true,如果該集合不允許重復并且已經包含指定的元素。返回false。部分子類的add方法可能會限制添加到集合中的元素類型,或者不會將NULL添加到集合中。
boolean addAll(Collection<? extends E> c)
將指定集合中的所有元素添加到此集合中。在添加過程中如果被添加的集合發(fā)生了更改,addAll方法不具有冪等性。
void clear()
清空掉集合中的所有元素
boolean contains(Object o)
如果集合中包含指定元素那么返回true。特別的,如果集合中也包含NULL元素的時候并且要查找的元素也是NULL的時候也返回true。
boolean containsAll(Collection<?> c)
如果該集合中包含指定集合中的所有元素的時候返回true。
boolean isEmpty()
如果集合中沒有元素返回true。
boolean remove(Object o)
刪除集合中的指定的元素。如果存在NULL,也刪除。
boolean removeAll(Collection<?> c)
刪除當前集合中所有等于指定集合中的元素。
boolean retainAll(Collection<?> c)
僅保留該指定集合中存在的所有元素。其余刪除
int size()
返回該集合中元素的個數(shù)。如果超過了Integer.MAX_VALUE,那么返回Integer.MAX_VALUE。
Object[] toArray()
這個方法是集合和數(shù)組轉化的橋梁。
見名知意,返回包含此集合中所有元素的數(shù)組。如果這個集合的迭代器保證元素有序,那么該方法與其迭代器中元素順序一致。并且該方法返回的數(shù)組是拷貝出來的(某些集合底層數(shù)組實現(xiàn),區(qū)別這個),可以進行任意的更改。
<T> T[] toArray(T[] a)
該方法可以對返回的數(shù)組類型進行精確控制。而非像toArray方法一樣返回Object[]。
返回集合中所有元素到該數(shù)組中。如果這個數(shù)組可以容納下的話,否則返回一個新new的數(shù)組,容量和集合中元素數(shù)量一致。如果指定的數(shù)組容量大于集合中元素個數(shù),數(shù)組空閑位置填NULL。如果這個集合的Iterator具有順序性的話,數(shù)組元素順序與該迭代器一致。
Collection接口在Java8中的函數(shù)擴展
新增抽象方法:

新增重寫方法splIterator以及繼承方法forEach。

Iterator 接口
從剛才的Colllection接口的結構體中我們可以看出,該Collection接口實現(xiàn)了Iterable接口,說明了Collection接口是可迭代的。而這個Iterable接口又只有一個iterator方法。返回值是Iterator對象。即返回的是對應實現(xiàn)類的迭代器對象。

如圖,Iterator接口只有三個抽象函數(shù)。
首先我們先來對Iterator接口了解一下:

Iterator Api詳解
boolean hasNext()
如果迭代器中還有元素那么返回true。
E next()
返回迭代器中游標的下一元素
void remove()
從迭代器指向的 collection 中移除迭代器返回的最后一個元素。每次調用 next 后只能調用一次此方法。如果進行迭代時用調用此方法之外的其他方式修改了該迭代器所指向的 collection,則迭代器的行為是不確定的。
ArrayList的自定義迭代器
我們拿了一個Collection接口的實現(xiàn)類來看了一下。

ArrayList寫了一個內部類Itr來實現(xiàn)Iterator接口作為自己的迭代器。
變量:
- cursor:迭代器下一個要返回的元素的索引
- lastRet:迭代器最后一個返回的元素的索引
- expectedModCount:期望中ArrayList集合的底層數(shù)組容器的修改次數(shù),來和父類AbstractList中設定的變量modCount來進行比較。
方法:
- hasNext:判斷游標是否指到了size即可。因為底層容器是數(shù)組所以size位置沒有元素當游標指到的時候就是迭代器結束迭代的時候。
- next:首先判斷容器是否在Itr初始化之后就已經被其他線程進行了更改。如果是那么就會根據(jù)checkForComodification方法的判斷規(guī)則來跑出一個異常。然后就是通過游標來對容器進行迭代,并動態(tài)的修改lastRet的值。
- remove: 因為是更改操作,先判斷一下容器是否被動過。然后調用該ArrayList類的實例的remove方法刪除掉指定索引處的元素。此時動態(tài)的維護cursor和lastRet,expectedModCount變量。此處可有看出Iterator接口的remove方法的解釋是什么意思了。
- checkForComodification:該方法就是簡單的對expectedModCount變量和AbstractList類中的modCount變量進行判斷看是否容器被其他線程更改了。這也就是為什么Iterator接口的remove方法的釋義說迭代器的行為是不確定的。這里ArrayList由于是線程不安全的類,所以在其迭代器中設定了如果線程間沖突時的處理規(guī)則。
List 接口
List接口Api一覽

- 重寫了Collection接口的一些列函數(shù)。
- 繼承了add和addAll兩個函數(shù)的規(guī)則。
- 新增了一些列函數(shù)。
List集合的特點

和Set集合最大的不同即紅框中所述:
- 有序
- 允許重復元素
從Api列表中我們可以看到List接口定義了一個listIterator函數(shù),返回一個ListIterator接口。該接口繼承自Iterator接口,并提供了更多的函數(shù)。
ListIterator接口

從ListIterator接口的Api描述中總結出的幾點就是:
- 相比于hasNext函數(shù)多了一個對應的hasPrevious函數(shù),來檢測游標指向的元素是否具有前驅元素。
- 相比于next函數(shù)多了一個previous函數(shù),來獲取游標指向的元素的前一位元素。
- 多了nextIndex和previousIndex函數(shù),用來返回迭代器下一元素和前一迭代過的元素的索引。
- 多了set函數(shù)和add函數(shù),set函數(shù)允許替換掉previous和next函數(shù)操作后返回的元素。add函數(shù)允許將元素插入到容器中游標前的位置。
List常見實現(xiàn)類

- ArrayList:
底層數(shù)據(jù)結構是數(shù)組。線程不安全 - LinkedList:
底層數(shù)據(jù)結構是鏈表。線程不安全 - Vector:
底層數(shù)據(jù)結構是數(shù)組。線程安全
Set 接口
Set接口Api一覽

- 并沒有新增自己的函數(shù)
- 重寫了Collection接口的部分函數(shù)
- 繼承了add函數(shù)和addAll函數(shù)
Set集合特點

相比于List集合最大的區(qū)別:
- 不包含重復元素。
這里我們強調一下,有些地方說Set集合是無序的,其實是不嚴謹?shù)摹?梢钥吹絡dk注釋中是沒有指明這一點的,那么List集合的注釋中的有序和有些人常說的Set集合是無序的是什么意思呢?
首先要搞清楚、Java中有序和無序的概念:
有序指的是存儲順序與添加順序相同,并且可以通過下標訪問,List就是這樣。
無序剛好相反,指的是存儲順序與添加順序無關,沒有下標,當然也不可能通過下標訪問,Set就是如此。
這里需要注意的是,有序、無序中的“序”與我們平常所說的“順序”無關。
而TreeSet是無序,但又是排好序的。即添加順序與存儲順序無關,但是其中的對象實現(xiàn)了排序。
Set集合常用子類

- HashSet:底層數(shù)據(jù)結構是哈希表(是一個元素為鏈表的數(shù)組)
- TreeSet:底層數(shù)據(jù)結構是紅黑樹(是一個自平衡的二叉樹)。保證元素的排序方式
- LinkedHashSet:底層數(shù)據(jù)結構由哈希表和鏈表組成。