1. 程式人生 > 實用技巧 >java Conllection介面及其實現類

java Conllection介面及其實現類

Java集合大致可分為Set、List和Map三種體系,其中Set代表無序、不可重複的集合;List代表有序、重複的集合;
而Map則代表具有對映關係的集合。Java 5之後,增加了Queue體系集合,代表一種佇列集合實現。Java集合框架主要由Collection和Map兩個根介面及其子介面、實現類組成。


Collection介面
介面是Set、List和Queue介面的父介面,方法有
  • add(Object o):新增元素
  • addAll(Collection c):新增c集合中所有元素
  • clear():刪除Collection物件中的所有元素
  • contains(Object o):是否包含o元素,底層呼叫為equals()方法
  • containsAll(Collectionc):是否包含集合c中的所有元素
  • iterator():返回Iterator物件,用於遍歷集合中的元素
  • remove(Object o):移除元素
  • removeAll(Collection c):從集合中移出它和C物件相同的元素。而對於A中含有而B中不含有的物件,不移除。
  • retainAll(Collection c):相當於求與c的交集
  • size():返回元素個數
  • toArray():把集合轉換為一個數組
  • hashCode():返回字串的雜湊碼。
Collection介面中並未重寫toString(),toString的重寫是在它的實現類AbstractCollection中實現的。

Set子介面

Set介面是Collection介面的子類,其繼承了所有方法,HashSet集合則實現了Set介面,其內部儲存資料時依靠雜湊表,一個類似陣列和連結串列的結合體。設定空集合時,存在預設的容量和載入因子,再用HashSet物件呼叫add方法時,其實是先比較其Hash值,若是沒有的話,則直接新增到集合中,若有的話,則再equals下比較其內容(因為有可能內容不一樣,但是其Hash值一樣),若是內容不一樣,則在這個地址下新增(鏈式),若是一樣的話,則丟掉。注意就保證了其的唯一性。(以後定義變數時,都需要重寫其hashcode和equals方法)至於LinkedHashSet則在HashSet基礎上保證了其的有序性(取出和存入順序一樣)。

HashSet

由HashSet的原始碼可知,HashSet底層就是一個HashMap。我們在往HashSet中儲存資料的時候,HashSet新增的元素是存放在HashMap的key位置上,而value取了預設常量PRESENT,是一個空物件。
HashSet底層的資料結構是一個雜湊表,存在HashSet中的元素應該重寫其hashCode()方法,故存在HashMap中的key,應該 重寫其hashCode()方法。HashSet集合不能保證迭代順序與元素的儲存順序相同。

擴容機制:預設初始容量為16。載入因子為0.75:即當 元素個數 超過 容量長度的0.75倍 時,進行擴容。擴容增量:原容量的 1 倍

LinkedHashSet類

LinkedHashSet具有set集合不重複的特點,同時具有可預測的迭代順序,也就是我們插入的順序。因為是HashSet的子類,所以也是保證元素唯一的,與HashSet的原理一樣。

此實現與 HashSet 的不同之處在於,LinkedHashSet 維護著一個運行於所有條目的雙重連結列表。此連結列表定義了迭代順序,該迭代順序可為插入順序或是訪問順序。

SortSet介面與TreeSet類

TreeSet為SortSet的一個實現類,該類可以按照元素大小進行排序,但是存入的物件必須實現Comparable<T>介面並對其比較方法進行重寫,可以比較出物件比較後的大小。或者使用java.util.Comparator;來單獨編寫一個比較器,建立TreeSet集合的時候提供這個比較器,如果未實現介面或提供比較器會丟擲ClassCastException。

新增方法:

  1. first():返回第一個元素
  2. last():返回最後一個元素
  3. lower(Object o):返回指定元素之前的元素
  4. higher(Obect o):返回指定元素之後的元素
  5. subSet(fromElement, toElement):返回子集合

EnumSet類

EnumSet這是一個用來操作Enum的集合,EnumSet中的所有元素都必須是指定列舉型別的列舉值,它是一個抽象類,有兩個繼承類:JumboEnumSet和RegularEnumSet。在使用的時候,需要確定列舉型別。它的特點也是速度非常快。
EnumSet是一個抽象類,不能直接通過new新建,noneOf方法會建立一個指定列舉型別的EnumSet,不含任何元素。建立的EnumSet物件的實際型別是EnumSet的子類,執行緒不安全

List介面

List子介面是有序集合。有索引,包含了一些帶索引的方法,還允許儲存重複的元素。

void add(int index, E element) 在指定 index 索引處理插入元素 element boolean addAll(int index, Collection<? extends E> c) 在指定 index 索引處理插入集合元素 c
E remove(int index) 刪除指定索引 index 處的元素

E set(int index, E element) 修改指定索引 index 處的元素為 element

E get(int index) + int size() for迴圈遍歷集合中的每一個元素

ListIterator<E> listIterator() 通過列表迭代器遍歷集合中的每一個元素 ListIterator<E> listIterator(int index) 通過列表迭代器從指定索引處開始正向或者逆向遍歷集合中的元素

E get(int index) 獲取指定索引處的元素
int indexOf(Object o) 從左往右查詢,獲取指定元素在集合中的索引,如果元素不存在返回 -1
int lastIndexOf(Object o) 從右往左查詢,獲取指定元素在集合中的索引,如果元素不存在返回 -1
List<E> subList(int fromIndex, int toIndex) 擷取從 fromIndex 開始到 toIndex-1 處的元素
ArrayList

ArrayList 是一個陣列佇列,相當於動態陣列。與Java中的陣列相比,它的容量能動態增長。它繼承於AbstractList,實現了List, RandomAccess, Cloneable, java.io.Serializable這些介面。ArrayList繼承了AbstractList,實現了List

它是一個數組佇列,提供了相關的新增、刪除、修改、遍歷等功能。

ArrayList實現了RandmoAccess介面,即提供了隨機訪問功能。RandmoAccess是java中用來被List實現,為List提供快速訪問功能的。在ArrayList中,我們即可以通過元素的序號快速獲取元素物件;這就是快速隨機訪問。

ArrayList 實現了Cloneable介面,即覆蓋了函式clone(),能被克隆。

ArrayList 實現java.io.Serializable介面,這意味著ArrayList支援序列化,能通過序列化去傳輸。ArrayList的操作不是執行緒安全的。

擴容機制:當ArrayList不為空時,並且它的大小不超過10時,它的容量都是10.但當大小從10增加到11時,容量變成了15,擴大了1.5倍。
如果ArrayList的容量大於MAX_ARRAY_SIZE,來比較 minCapacity 和 MAX_ARRAY_SIZE,如果minCapacity大於最大容量,則新容量則為Integer.MAX_VALUE,否則,新容量大小則為 MAX_ARRAY_SIZE
即為 Integer.
MAX_VALUE - 8

Vector

Vector 類實現了一個動態陣列。和 ArrayList 很相似,但是兩者是不同的:

  • Vector 是同步訪問的。
  • Vector 包含了許多傳統的方法,這些方法不屬於集合框架。

Vector 主要用在事先不知道陣列的大小,或者只是需要一個可以改變大小的陣列的情況。

第一種構造方法建立一個預設的向量,預設大小為10;

Vector()

第二種構造方法建立指定大小的向量。
Vector(int size)
第三種構造方法建立指定大小的向量,並且增量用 incr 指定。增量表示向量每次增加的元素數目。
Vector(int size,int incr)
第四種構造方法建立一個包含集合 c 元素的向量:
Vector(Collection c)
Stack

棧是Vector的一個子類,它實現了一個標準的後進先出的棧。它也是執行緒安全的。

堆疊只定義了預設建構函式,用來建立一個空棧。 堆疊除了包括由Vector定義的所有方法,也定義了自己的一些方法。

Stack()除了由Vector定義的所有方法,自己也定義了一些方法:

E push(E item)    把項壓入堆疊頂部

E pop()    移除堆疊頂部的物件,並作為此函式的值返回該物件。

E peek()    檢視堆疊頂部的物件,但不從堆疊中移除它。

boolean empty()    測試堆疊是否為空。

int search(Object o)    返回物件在堆疊中的位置,以 1 為基數。

Linkedlist
它繼承了AbstractSequentialList 類,同時也實現了 Deque 介面

Linkedlist是線性資料結構,其中元素不儲存在連續的位置,每個元素都是具有資料部分和地址部分的獨立物件。元素使用指標和地址進行連結。每個元素被稱為節點。由於插入和刪除的動態性和易用性,它們優於陣列。

它也有一些缺點,比如節點不能直接訪問,我們需要從頭開始,然後通過連結到達我們希望訪問的節點。 

為了將元素儲存在連結串列中,我們使用一個雙向連結串列,它提供了一個線性資料結構,並且還用於繼承一個抽象類並實現list和deque介面。

以下情況使用 ArrayList :

  • 頻繁訪問列表中的某一個元素。
  • 只需要在列表末尾進行新增和刪除元素操作。

以下情況使用 LinkedList :


  • 你需要通過迴圈迭代來訪問列表中的某些元素。
  • 需要頻繁的在列表開頭、中間、末尾等位置進行新增和刪除元素操作。

Queue子介面

Queue介面與List、Set同一級別,都是繼承了Collection介面。LinkedList實現了Queue介面。
佇列的主要特點是在基本的集合方法之外,還提供特殊的插入、獲取和檢驗操作。每個操作都提供兩個方法,一種返回異常,一種返回null或者false.
佇列一般滿足先進先出規則(FIFO),除了優先佇列(priority queue)和棧(stack),但是棧是FILO(先進後出規則),優先佇列自己定義了排序規則。
佇列不允許插入null元素,但是LinkedList可以

 java.ulil.concurrent包提供了阻塞佇列的4個變種。預設情況下,LinkedBlockingQueue的容量是沒有上限的,但是也可以選擇指定其最大容量,它是基於連結串列的佇列,此佇列按 FIFO(先進先出)排序元素。

ArrayBlockingQueue在構造時需要指定容量, 並可以選擇是否需要公平性,如果公平引數被設定true,等待時間最長的執行緒會優先得到處理(其實就是通過將ReentrantLock設定為true來 達到這種公平性的:即等待時間最長的執行緒會先操作)。通常,公平性會使你在效能上付出代價,只有在的確非常需要的時候再使用它。它是基於陣列的阻塞迴圈隊 列,此佇列按 FIFO(先進先出)原則對元素進行排序。

PriorityBlockingQueue是一個帶優先順序的 佇列,而不是先進先出佇列。元素按優先順序順序被移除,該佇列也沒有上限(看了一下原始碼,PriorityBlockingQueue是對 PriorityQueue的再次包裝,是基於堆資料結構的,而PriorityQueue是沒有容量限制的,
與ArrayList一樣,所以在優先阻塞 佇列上put時是不會受阻的。雖然此佇列邏輯上是無界的,但是由於資源被耗盡,所以試圖執行新增操作可能會導致 OutOfMemoryError),但是如果佇列為空,那麼取元素的操作take就會阻塞,所以它的檢索操作take是受阻的。
另外,往入該佇列中的元 素要具有比較能力。
最後,DelayQueue(基於PriorityQueue來實現的)是一個存放Delayed 元素的無界阻塞佇列,只有在延遲期滿時才能從中提取元素。該佇列的頭部是延遲期滿後儲存時間最長的 Delayed 元素。
如果延遲都還沒有期滿,則佇列沒有頭部,並且poll將返回null。當一個元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一個小於或等於零的值時,則出現期滿,poll就以移除這個元素了。此佇列不允許使用 null 元素。 下面是延遲介面:
- add(E e) 插入一個元素到佇列中,失敗時返回IllegalStateException (佇列容量不夠)
- element() 返回佇列頭部的元素
- offer(E e) 插入一個元素到佇列中,失敗時返回false
- peek() 返回佇列頭部的元素,佇列為空時返回null
- poll() 返回並移除佇列的頭部元素,佇列為空時返回null
- remove() 返回並移除佇列的頭部元素

Deque介面
雙端佇列是一種線性集合,可以從兩端操作的佇列。
  1. add(E e) 將新元素新增到佇列的尾端(當不超過佇列的容量時)
  2. addFirst(E e) 將新元素新增到佇列的頭部
  3. addLast(E e) 將新元素新增到佇列的尾部
  4. contains(Object o) 雙端佇列是否含有物件o
  5. descendingIterator()倒敘返回佇列的迭代器
  6. element() 返回佇列的頭部元素
  7. getFirst() 獲取頭部元素
  8. getLast() 獲取尾部元素
  9. iterator() 迭代佇列
  10. offer(E e) 將新元素插入到佇列尾部
  11. offerFirst(E e) 將新元素新增到佇列的頭部
  12. offerLast(E e) 將新元素新增到佇列的尾部
  13. peek() 返回佇列的頭部元素
  14. peekFirst() 獲取頭部元素
  15. peekLast() 獲取尾部元素
  16. pool() 返回並移除佇列的頭部元素
  17. poolFirst() 獲取並移除頭部元素
  18. poolLast() 獲取並移除尾部元素
  19. pop() 將一個元素出棧
  20. push(E e) 講一個元素壓入棧
  21. remove() 移除佇列的頭部元素
  22. remove(Object o) 移除佇列中第一個o
  23. removeFirst() 移除佇列的頭部元素
  24. removeFirstOccurrence(Object o) 移除佇列中第一個o
  25. removeLast() 移除佇列的尾部元素
  26. removeLastOccurrence(Object o) 移除佇列中最後一個o