Collection接口詳解


集合家族

Collection接口

Collection即單列集合。統一定義了一套單列集合的接口

Collection接口Api一覽

由圖中我們可以看出:

  • 重寫了Iterable接口的iterator方法。
  • 重寫了Object類的equals和hashCode方法。
  • 定義了一系列待實現方法。

爲什麼重寫Iterable接口的iterator方法

很直觀。我們一看註釋其實就能大概明白Java設計人員的思路,其實Iterable接口可以看成許多容器類共同特性被提取出來做了接口。而相對於不同容器,這個共有特性的具體實現細節又不同。既然不同所以又要自己定義自己系列的迭代器規則,並讓所有實現類都遵循這個規則。

對於Collection接口來說,它規定子接口及其實現類都必須滿足它重新設定的規則。

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)

將指定集合中的所有元素添加到此集合中。在添加過程中如果被添加的集合發生了更改,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()

返回該集合中元素的個數。如果超過了Integer.MAX_VALUE,那麼返回Integer.MAX_VALUE。

  • Object[] toArray()

這個方法是集合和數組轉化的橋樑。

見名知意,返回包含此集合中所有元素的數組。如果這個集合的迭代器保證元素有序,那麼該方法與其迭代器中元素順序一致。並且該方法返回的數組是拷貝出來的(某些集合底層數組實現,區別這個),可以進行任意的更改。

  • <T> T[] toArray(T[] a)

該方法可以對返回的數組類型進行精確控制。而非像toArray方法一樣返回Object[]

返回集合中所有元素到該數組中。如果這個數組可以容納下的話,否則返回一個新new的數組,容量和集合中元素數量一致。如果指定的數組容量大於集合中元素個數,數組空閒位置填NULL。如果這個集合的Iterator具有順序性的話,數組元素順序與該迭代器一致。

Collection接口在Java8中的函數擴展

新增抽象方法:

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

Iterator 接口

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

如圖,Iterator接口只有三個抽象函數。

首先我們先來對Iterator接口瞭解一下:

Iterator Api詳解

  • boolean hasNext()

    如果迭代器中還有元素那麼返回true。

  • E next()

    返回迭代器中游標的下一元素

  • void remove()

    從迭代器指向的 collection 中移除迭代器返回的最後一個元素。每次調用 next 後只能調用一次此方法。如果進行迭代時用調用此方法之外的其他方式修改了該迭代器所指向的 collection,則迭代器的行爲是不確定的。

ArrayList的自定義迭代器

我們拿了一個Collection接口的實現類來看了一下。

ArrayList寫了一個內部類Itr來實現Iterator接口作爲自己的迭代器。

變量:
- cursor:迭代器下一個要返回的元素的索引
- lastRet:迭代器最後一個返回的元素的索引
- expectedModCount:期望中ArrayList集合的底層數組容器的修改次數,來和父類AbstractList中設定的變量modCount來進行比較。

方法:
- hasNext:判斷遊標是否指到了size即可。因爲底層容器是數組所以size位置沒有元素當遊標指到的時候就是迭代器結束迭代的時候。
- next:首先判斷容器是否在Itr初始化之後就已經被其他線程進行了更改。如果是那麼就會根據checkForComodification方法的判斷規則來跑出一個異常。然後就是通過遊標來對容器進行迭代,並動態的修改lastRet的值。
- remove: 因爲是更改操作,先判斷一下容器是否被動過。然後調用該ArrayList類的實例的remove方法刪除掉指定索引處的元素。此時動態的維護cursor和lastRet,expectedModCount變量。此處可有看出Iterator接口的remove方法的解釋是什麼意思了。
- checkForComodification:該方法就是簡單的對expectedModCount變量和AbstractList類中的modCount變量進行判斷看是否容器被其他線程更改了。這也就是爲什麼Iterator接口的remove方法的釋義說迭代器的行爲是不確定的。這裏ArrayList由於是線程不安全的類,所以在其迭代器中設定了如果線程間衝突時的處理規則。

List 接口

List接口Api一覽

  • 重寫了Collection接口的一些列函數。
  • 繼承了add和addAll兩個函數的規則。
  • 新增了一些列函數。

List集合的特點

和Set集合最大的不同即紅框中所述:
- 有序
- 允許重複元素

從Api列表中我們可以看到List接口定義了一個listIterator函數,返回一個ListIterator接口。該接口繼承自Iterator接口,並提供了更多的函數。

ListIterator接口

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

List常見實現類

  • ArrayList:
    底層數據結構是數組。線程不安全
  • LinkedList:
    底層數據結構是鏈表。線程不安全
  • Vector:
    底層數據結構是數組。線程安全

Set 接口

Set接口Api一覽

  • 並沒有新增自己的函數
  • 重寫了Collection接口的部分函數
  • 繼承了add函數和addAll函數

Set集合特點

相比於List集合最大的區別:
- 不包含重複元素。

這裏我們強調一下,有些地方說Set集合是無序的,其實是不嚴謹的。可以看到jdk註釋中是沒有指明這一點的,那麼List集合的註釋中的有序和有些人常說的Set集合是無序的是什麼意思呢?


首先要搞清楚、Java中有序和無序的概念:

有序指的是存儲順序與添加順序相同,並且可以通過下標訪問,List就是這樣。

無序剛好相反,指的是存儲順序與添加順序無關,沒有下標,當然也不可能通過下標訪問,Set就是如此。

這裏需要注意的是,有序、無序中的“序”與我們平常所說的“順序”無關。

而TreeSet是無序,但又是排好序的。即添加順序與存儲順序無關,但是其中的對象實現了排序。


Set集合常用子類


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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章