Java集合框架詳解(全)

1、Java集合框架概述html

 

 

  集合能夠看做是一種容器,用來存儲對象信息。全部集合類都位於java.util包下,但支持多線程的集合類位於java.util.concurrent包下。java

  數組與集合的區別以下:算法

  1)數組長度不可變化並且沒法保存具備映射關係的數據;集合類用於保存數量不肯定的數據,以及保存具備映射關係的數據。數組

  2)數組元素既能夠是基本類型的值,也能夠是對象;集合只能保存對象。安全

  Java集合類主要由兩個根接口CollectionMap派生出來的,Collection派生出了三個子接口:List、Set、Queue(Java5新增的隊列),所以Java集合大體也可分紅List、Set、Queue、Map四種接口體系,(注意:Map不是Collection的子接口)。微信

  其中List表明了有序可重複集合,可直接根據元素的索引來訪問;Set表明無序不可重複集合,只能根據元素自己來訪問;Queue是隊列集合;Map表明的是存儲key-value對的集合,可根據元素的key來訪問value。數據結構

  上圖中淡綠色背景覆蓋的是集合體系中經常使用的實現類,分別是ArrayList、LinkedList、ArrayQueue、HashSet、TreeSet、HashMap、TreeMap等實現類。多線程

2、Java集合常見接口及實現類框架

1. Collection接口常見方法(來源於Java API)性能

2. Set集合

   Set集合與Collection的方法相同,因爲Set集合不容許存儲相同的元素,因此若是把兩個相同元素添加到同一個Set集合,則添加操做失敗,新元素不會被加入,add()方法返回false。爲了幫助理解,請看下面代碼示例:

public class Test { public static void main(String[] args) { Set<String> set = new HashSet<String>(); set.add("hello world"); set.add("hello 冰湖一角"); set.add("hello 冰湖一角");//添加不進去
        System.out.println("集合中元素個數:"+set.size()); System.out.println("集合中元素爲:"+set.toString()); } }

運行結果以下:

集合中元素個數:2
集合中元素爲:[hello world, hello 冰湖一角]

分析:因爲String類中重寫了hashCode()和equals()方法,用來比較指向的字符串對象所存儲的字符串是否相等。因此這裏的第二個"hello 冰湖一角"是加不進去的。

下面着重介紹Set集合幾個經常使用實現類:

1)HashSet類

  HashSet是Set集合最經常使用實現類,是其經典實現。HashSet是按照hash算法來存儲元素的,所以具備很好的存取和查找性能。

  HashSet具備以下特色:

  ♦ 不能保證元素的順序。

  ♦ HashSet不是線程同步的,若是多線程操做HashSet集合,則應經過代碼來保證其同步。

  ♦ 集合元素值能夠是null。

  HashSet存儲原理以下:

  當向HashSet集合存儲一個元素時,HashSet會調用該對象的hashCode()方法獲得其hashCode值,而後根據hashCode值決定該對象的存儲位置。HashSet集合判斷兩個元素相等的標準是(1)兩個對象經過equals()方法比較返回true;(2)兩個對象的hashCode()方法返回值相等。所以,若是(1)和(2)有一個不知足條件,則認爲這兩個對象不相等,能夠添加成功。若是兩個對象的hashCode()方法返回值相等,可是兩個對象經過equals()方法比較返回false,HashSet會以鏈式結構將兩個對象保存在同一位置,這將致使性能降低,所以在編碼時應避免出現這種狀況。

  HashSet查找原理以下:

  基於HashSet以上的存儲原理,在查找元素時,HashSet先計算元素的HashCode值(也就是調用對象的hashCode方法的返回值),而後直接到hashCode值對應的位置去取出元素便可,這就是HashSet速度很快的緣由。

   重寫hashCode()方法的基本原則以下:

   ♦ 在程序運行過程當中,同一個對象的hashCode()方法返回值應相同。

  ♦ 當兩個對象經過equals()方法比較返回true時,這兩個對象的hashCode()方法返回值應該相等。

  ♦ 對象中用做equals()方法比較標準的實例變量,都應該用於計算hashCode值。

 2)LinkedHashSet類

   LinkedHashSet是HashSet的一個子類,具備HashSet的特性,也是根據元素的hashCode值來決定元素的存儲位置。但它使用鏈表維護元素的次序,元素的順序與添加順序一致。因爲LinkedHashSet須要維護元素的插入順序,所以性能略低於HashSet,但在迭代訪問Set裏的所有元素時由很好的性能。

 3)TreeSet類

  TreeSet時SortedSet接口的實現類,TreeSet能夠保證元素處於排序狀態,它採用紅黑樹的數據結構來存儲集合元素。TreeSet支持兩種排序方法:天然排序和定製排序,默認採用天然排序。

  ♦ 天然排序

  TreeSet會調用集合元素的compareTo(Object obj)方法來比較元素的大小關係,而後將元素按照升序排列,這就是天然排序。若是試圖將一個對象添加到TreeSet集合中,則該對象必須實現Comparable接口,不然會拋出異常。當一個對象調用方法與另外一個對象比較時,例如obj1.compareTo(obj2),若是該方法返回0,則兩個對象相等;若是返回一個正數,則obj1大於obj2;若是返回一個負數,則obj1小於obj2。

  Java經常使用類中已經實現了Comparable接口的類有如下幾個:

  ♦ BigDecimal、BigDecimal以及全部數值型對應的包裝類:按照它們對應的數值大小進行比較。

  ♦ Charchter:按照字符的unicode值進行比較。

  ♦ Boolean:true對應的包裝類實例大於false對應的包裝類實例。

  ♦ String:按照字符串中的字符的unicode值進行比較。

  ♦ Date、Time:後面的時間、日期比前面的時間、日期大。

  對於TreeSet集合而言,它判斷兩個對象是否相等的標準是:兩個對象經過compareTo(Object obj)方法比較是否返回0,若是返回0則相等。

   ♦ 定製排序

  想要實現定製排序,須要在建立TreeSet集合對象時,提供一個Comparator對象與該TreeSet集合關聯,由Comparator對象負責集合元素的排序邏輯。

  綜上:天然排序實現的是Comparable接口,定製排序實現的是Comparator接口。(具體代碼實現會在後續章節中講解)

 4)EnumSet類

  EnumSet是一個專爲枚舉類設計的集合類,不容許添加null值。EnumSet的集合元素也是有序的,它以枚舉值在Enum類內的定義順序來決定集合元素的順序。

5)各Set實現類的性能分析

  HashSet的性能比TreeSet的性能好(特別是添加,查詢元素時),由於TreeSet須要額外的紅黑樹算法維護元素的次序,若是須要一個保持排序的Set時才用TreeSet,不然應該使用HashSet。

  LinkedHashSet是HashSet的子類,因爲須要鏈表維護元素的順序,因此插入和刪除操做比HashSet要慢,但遍歷比HashSet快。

  EnumSet是全部Set實現類中性能最好的,但它只能 保存同一個枚舉類的枚舉值做爲集合元素。

  以上幾個Set實現類都是線程不安全的,若是多線程訪問,必須手動保證集合的同步性,這在後面的章節中會講到。

3. List集合

  List集合表明一個有序、可重複集合,集合中每一個元素都有其對應的順序索引。List集合默認按照元素的添加順序設置元素的索引,能夠經過索引(相似數組的下標)來訪問指定位置的集合元素。

  實現List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。

1)ArrayList

      ArrayList是一個動態數組,也是咱們最經常使用的集合,是List類的典型實現。它容許任何符合規則的元素插入甚至包括null。每個ArrayList都有一個初始容量(10),該容量表明瞭數組的大小。隨着容器中的元素不斷增長,容器的大小也會隨着增長。在每次向容器中增長元素的同時都會進行容量檢查,當快溢出時,就會進行擴容操做。因此若是咱們明確所插入元素的多少,最好指定一個初始容量值,避免過多的進行擴容操做而浪費時間、效率。

      ArrayList擅長於隨機訪問。同時ArrayList是非同步的。

2)LinkedList

     LinkedList是List接口的另外一個實現,除了能夠根據索引訪問集合元素外,LinkedList還實現了Deque接口,能夠看成雙端隊列來使用,也就是說,既能夠看成「棧」使用,又能夠看成隊列使用。

  LinkedList的實現機制與ArrayList的實現機制徹底不一樣,ArrayLiat內部以數組的形式保存集合的元素,因此隨機訪問集合元素有較好的性能;LinkedList內部以鏈表的形式保存集合中的元素,因此隨機訪問集合中的元素性能較差,但在插入刪除元素時有較好的性能。

3)Vector

      與ArrayList類似,可是Vector是同步的。因此說Vector是線程安全的動態數組。它的操做與ArrayList幾乎同樣。

4)Stack

     Stack繼承自Vector,實現一個後進先出的堆棧。Stack提供5個額外的方法使得Vector得以被看成堆棧使用。基本的push和pop 方法,還有peek方法獲得棧頂的元素,empty方法測試堆棧是否爲空,search方法檢測一個元素在堆棧中的位置。Stack剛建立後是空棧。

5)Iterator接口和ListIterator接口

  Iterator是一個接口,它是集合的迭代器。集合能夠經過Iterator去遍歷集合中的元素。Iterator提供的API接口以下:

  ♦ boolean hasNext():判斷集合裏是否存在下一個元素。若是有,hasNext()方法返回 true。
  ♦ Object next():返回集合裏下一個元素。
  ♦ void remove():刪除集合裏上一次next方法返回的元素。

  ListIterator接口繼承Iterator接口,提供了專門操做List的方法。ListIterator接口在Iterator接口的基礎上增長了如下幾個方法:

  ♦ boolean hasPrevious():判斷集合裏是否存在上一個元素。若是有,該方法返回 true。
  ♦ Object previous():返回集合裏上一個元素。
  ♦ void add(Object o):在指定位置插入一個元素。

  以上兩個接口相比較,不難發現,ListIterator增長了向前迭代的功能(Iterator只能向後迭代),ListIterator還能夠經過add()方法向List集合中添加元素(Iterator只能刪除元素)。

4. Map集合

  Map接口採用鍵值對Map<K,V>的存儲方式,保存具備映射關係的數據,所以,Map集合裏保存兩組值,一組值用於保存Map裏的key,另一組值用於保存Map裏的value,key和value能夠是任意引用類型的數據。key值不容許重複,能夠爲null。若是添加key-value對時Map中已經有重複的key,則新添加的value會覆蓋該key原來對應的value。經常使用實現類有HashMap、LinkedHashMap、TreeMap等。

  Map常見方法(來源於API)以下:

 1)HashMap與Hashtable

  HashMap與Hashtable是Map接口的兩個典型實現,它們之間的關係徹底相似於ArrayList與Vertor。HashTable是一個古老的Map實現類,它提供的方法比較繁瑣,目前基本不用了,HashMap與Hashtable主要存在如下兩個典型區別:

  ♦ HashMap是線程不安全,HashTable是線程安全的。

  ♦ HashMap可使用null值最爲key或value;Hashtable不容許使用null值做爲key和value,若是把null放進HashTable中,將會發生空指針異常。

  爲了成功的在HashMap和Hashtable中存儲和獲取對象,用做key的對象必須實現hashCode()方法和equals()方法。

  HashMap工做原理以下:

  HashMap基於hashing原理,經過put()和get()方法存儲和獲取對象。當咱們將鍵值對傳遞給put()方法時,它調用建對象的hashCode()方法來計算hashCode值,而後找到bucket位置來儲存值對象。當獲取對象時,經過建對象的equals()方法找到正確的鍵值對,而後返回對象。HashMap使用鏈表來解決碰撞問題,當發生碰撞了,對象將會存儲在鏈表的下一個節點中。

2)LinkedHashMap實現類

  LinkedHashMap使用雙向鏈表來維護key-value對的次序(其實只須要考慮key的次序便可),該鏈表負責維護Map的迭代順序,與插入順序一致,所以性能比HashMap低,但在迭代訪問Map裏的所有元素時有較好的性能。

3)Properties

  Properties類時Hashtable類的子類,它至關於一個key、value都是String類型的Map,主要用於讀取配置文件。

4)TreeMap實現類

  TreeMap是SortedMap的實現類,是一個紅黑樹的數據結構,每一個key-value對做爲紅黑樹的一個節點。TreeMap存儲key-value對時,須要根據key對節點進行排序。TreeMap也有兩種排序方式:

  ♦ 天然排序:TreeMap的全部key必須實現Comparable接口,並且全部的key應該是同一個類的對象,不然會拋出ClassCastException。

  ♦ 定製排序:建立TreeMap時,傳入一個Comparator對象,該對象負責對TreeMap中的全部key進行排序。

5)各Map實現類的性能分析

  ♦ HashMap一般比Hashtable(古老的線程安全的集合)要快

  ♦ TreeMap一般比HashMap、Hashtable要慢,由於TreeMap底層採用紅黑樹來管理key-value。

  ♦ LinkedHashMap比HashMap慢一點,由於它須要維護鏈表來爆出key-value的插入順序。  

 

如需轉載,請註明做者(冰湖一角)和連接https://www.cnblogs.com/bingyimeiling/p/10255037.html

 

歡迎關注微信公衆號【Java典籍】,收看更多Java技術乾貨!

   ▼微信掃一掃下圖↓↓↓二維碼關注