1. 程式人生 > >java集合和資料結構深入解讀

java集合和資料結構深入解讀

參考部落格 http://www.cnblogs.com/skywang12345/p/3323085.html
Java集合在java的世界中是非常重要的一部分,主要集合包括List列表,Set集合,Map對映還有Iterator迭代器、Enumeration列舉
集合的資料結構主要有集合、連結串列、佇列、棧、陣列、對映等
一、陣列:
Vector

1)、執行緒安全的,通過加鎖的方式實現
2)、長度可變,當長度不夠的時候,如果沒有初始化capacityIncrement>0,則會將長度擴充套件為原來的兩倍

ArrayList
1)、線性表,查詢速度快,更新速度慢(線上性表前面新增元素會將後邊的元素都後移動,如果前面刪除,會將後面元素前移,導致效能低)

LinkedList
1)、雙向連結串列,記錄了當前節點元素和前後節點的元素資訊,因此更新速度相對比較快,但是查詢速度相對慢點(隨機查詢一個元素:按照順序從列表的一端開始檢查,直到另外一端)

Stack
1)、先進後出(FILO, First In Last Out)。
2)、Stack也是通過陣列實現的,而非連結串列
3)、執行push時(即,將元素推入棧中),是通過將元素追加的陣列的末尾中。
   執行peek時(即,取出棧頂元素,不執行刪除),是返回陣列末尾的元素。
   執行pop時(即,取出棧頂元素,並將該元素從棧中刪除),是取出陣列末尾的元素,然後將該元素從陣列中刪除
      

二、map集合
Map主要介面:
1 )Map
2 )Map.Entry
3 )AbstractMap
4 )SortedMap
SortedMap的排序方式有兩種:自然排序 或者 使用者指定比較器
5 )NavigableMap
NavigableMap是繼承於SortedMap的介面。它是一個可導航的鍵-值對集合,具有了為給定搜尋目標報告最接近匹配項的導航方法
NavigableMap除了繼承SortedMap的特性外,它的提供的功能可以分為4類:
第1類,提供操作鍵-值對的方法。
               lowerEntry、floorEntry、ceilingEntry 和 higherEntry 方法,它們分別返回與小於、小於等於、大於等於、大於給定鍵的鍵關聯的 Map.Entry 物件。
               firstEntry、pollFirstEntry、lastEntry 和 pollLastEntry 方法,它們返回和/或移除最小和最大的對映關係(如果存在),否則返回 null。
第2類,提供操作鍵的方法。這個和第1類比較類似
               lowerKey、floorKey、ceilingKey 和 higherKey 方法,它們分別返回與小於、小於等於、大於等於、大於給定鍵的鍵。
第3類,獲取鍵集。
              navigableKeySet、descendingKeySet分別獲取正序/反序的鍵集。
第4類,獲取鍵-值對的子集。

6 )Dictionary

HashMap
1)只允許一條記錄的鍵為Null;允許多條記錄的值為Null;HashMap不支援執行緒的同步
2)HashMap的底層主要是基於陣列和連結串列(單向連結串列)來實現的
3)HashMap中主要是通過key的hashCode來計算hash值的,只要hashCode相同,計算出來的hash值就一樣。如果儲存的物件對多了,
就有可能不同的物件所算出來的hash值是相同的,這就出現了所謂的hash衝突。學過資料結構的同學都知道,
解決hash衝突的方法有很多,HashMap底層是通過連結串列來解決hash衝突的
4)遍歷效率問題:
第一種:
  Map map = new HashMap();
  Iterator iter = map.entrySet().iterator();
  while (iter.hasNext()) {
  Map.Entry entry = (Map.Entry) iter.next();
  Object key = entry.getKey();
  Object val = entry.getValue();
  }
  效率高,以後一定要使用此種方式!
第二種:
  Map map = new HashMap();
  Iterator iter = map.keySet().iterator();
  while (iter.hasNext()) {
  Object key = iter.next();
  Object val = map.get(key);
  }
  效率低,以後儘量少使用!原因:遍歷了兩次

LinkedHashMap
1)不支援執行緒同步,而且鍵和值都可以是null
2)與HashMap相比LinkedHashMap維護的是一個具有雙向連結串列的HashMap
3)LinkedHashMap支援2中排序一種是插入排序,一種是使用排序,最近使用的會移至尾部例如 M1 M2 M3 M4,使用M3後為 M1 M2 M4 M3了,
LinkedHashMap輸出時其元素是有順序的,而HashMap輸出時是隨機的,如果Map對映比較複雜而又要求高效率的話,最好使用LinkedHashMap,
但是多執行緒訪問的話可能會造成不同步,所以要用Collections.synchronizedMap來包裝一下,從而實現同步。其實現一般為:
    Map<String String> map = Collections.synchronizedMap(new LinkedHashMap(<String String));
4)由於的連結串列的增加、刪除操作是常量級的,故並不會帶來效能的損失

WeakHashMap
1)不支援執行緒同步,而且鍵和值都可以是null
2)散列表,它儲存的內容也是鍵值對(key-value)對映
3)WeakHashMap 中,當某個鍵不再正常使用時,會被從WeakHashMap中被自動移除
4)“弱鍵”如何被自動從WeakHashMap中刪除的步驟
 (01) 新建WeakHashMap,將“鍵值對”新增到WeakHashMap中。
           實際上,WeakHashMap是通過陣列table儲存Entry(鍵值對);每一個Entry實際上是一個單向連結串列,即Entry是鍵值對連結串列。
 (02) 當某“弱鍵”不再被其它物件引用,並被GC回收時。在GC回收該“弱鍵”時,這個“弱鍵”也同時會被新增到ReferenceQueue(queue)佇列中。
 (03) 當下一次我們需要操作WeakHashMap時,會先同步table和queue。table中儲存了全部的鍵值對,而queue中儲存被GC回收的鍵值對;同步它們,就是刪除table中被GC回收的鍵值對
5)Demo
public static void main(String[] args) throws Exception { 
        String a = new String("a"); 
        String b = new String("b"); 
        Map weakmap = new WeakHashMap(); 
        Map map = new HashMap(); 
        map.put(a, "aaa"); 
        map.put(b, "bbb"); 

         
        weakmap.put(a, "aaa"); 
        weakmap.put(b, "bbb"); 

        map.remove(a); 

        a=null; 
        b=null; 

        System.gc(); 
        Iterator i = map.entrySet().iterator(); 
        while (i.hasNext()) { 
            Map.Entry en = (Map.Entry)i.next(); 
            System.out.println("map:"+en.getKey()+":"+en.getValue()); 
        } 
        Iterator j = weakmap.entrySet().iterator(); 
        while (j.hasNext()) { 
            Map.Entry en = (Map.Entry)j.next(); 
            System.out.println("weakmap:"+en.getKey()+":"+en.getValue()); 
        } 
    }

HashTable
1)它支援執行緒的同步,它不允許記錄的鍵或者值為空;
2)Hashtable 繼承於Dictionary
3)和HashMap一樣,通過陣列和連結串列實現。Hashtable是通過"拉鍊法"實現的雜湊表,解決雜湊衝突問題
4)依賴了Enumeration,通過Enumeration遍歷Hashtable的鍵
根據keys()獲取Hashtable的集合
Enumeration enu = table.keys();
while(enu.hasMoreElements()) {
    System.out.println(enu.nextElement());
}  
根據elements()獲取Hashtable的集合
Enumeration enu = table.elements();
while(enu.hasMoreElements()) {
    System.out.println(enu.nextElement());
}

TreeMap
1)TreeMap是非同步的,它不允許記錄的鍵或者值為空
2)通過紅黑樹實現,TreeMap的本質是R-B Tree(紅黑樹)。
3)記錄根據鍵排序,預設是按升序排序,也可以指定排序的比較器

IdentityHashMap
1)非同步的,允許 null 值和 null
2)此為簡單的線性探頭雜湊表
3)當且僅當 (k1==k2) 時,才認為兩個鍵 k1 和 k2 相等(在正常 Map 實現(如 HashMap)中,
 當且僅當滿足下列條件時才認為兩個鍵 k1 和 k2 相等:(k1==null ? k2==null : e1.equals(e2)))。
4)key允許重複,只要兩個物件的地址不相等即可
5)Demo
 public static void main(String[] args) {
  IdentityHashMap ihm = new IdentityHashMap();
  // 下面兩行程式碼向IdentityHashMap物件新增兩個key-value對
  ihm.put(new String("語文"), 89);
  ihm.put(new String("語文"), 78);
  // 下面兩行程式碼只會向IdentityHashMap物件新增一個key-value對
  ihm.put("java", 93);
  ihm.put("java", 98);
  System.out.println(ihm);
 } 

三、set集合
(01) Set 是繼承於Collection的介面。它是一個不允許有重複元素的集合。
(02) AbstractSet 是一個抽象類,它繼承於AbstractCollection,AbstractCollection實現了Set中的絕大部分函式,為Set的實現類提供了便利。
(03) HastSet 和 TreeSet 是Set的兩個實現類。
        HashSet依賴於HashMap,它實際上是通過HashMap實現的。HashSet中的元素是無序的。
        TreeSet依賴於TreeMap,它實際上是通過TreeMap實現的。TreeSet中的元素是有序的
HashSet
1)HashSet是非同步的,HashSet允許使用 null 元素
2)通過HashMap實現,hashMap儲存的是key-value,hashSet儲存資料時候,value用空物件

LinkedHashSet
1)不支援執行緒同步
2)通過LinkedHashMap實現

TreeSet
1)TreeSet是非同步的
2)TreeSet是基於TreeMap實現的。TreeMap儲存的是key-value,hashSet儲存資料時候,value用空物件
3)TreeSet中的元素支援2種排序方式:自然排序 或者 根據建立TreeSet 時提供的 Comparator 進行排序

四、迭代、列舉
區別;
(01) 函式介面不同
        Enumeration只有2個函式介面。通過Enumeration,我們只能讀取集合的資料,而不能對資料進行修改。
        Iterator只有3個函式介面。Iterator除了能讀取集合的資料之外,也能資料進行刪除操作。
(02) Iterator支援fail-fast機制,而Enumeration不支援。

五、佇列

1、Queue:佇列是一種特殊的線性表,它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作,FIFO
2、Deque:雙端佇列是指既可以在表的前端進行插入和刪除操作,又可以在表的後端進行插入和刪除操作
3、ArrayDeque:陣列實現的雙線向列
4、PriorityQueue:
1)在PriorityQueue中,當你新增元素到Queue中時,實現了自動排序。根據你使用的PriorityQueue的不同構造器,Queue元素的順序要麼基於他們的自然順序要麼通過PriorirtyQueue構造器傳入的Comparator來確定
2)DEMO
PriorityQueue<Object> priorityQueue =  new PriorityQueue(6, new Comparator<Object>()
 {
  public int compare(Object a, Object  b)
       {
          System.out.println("Comparing Populations");
          if (a.hashCode()>b.hashCode())
        return 1;
   else if (a.hashCode()<b.hashCode())
            return -1;
      else
    return 0;
       }
  }
 );  

六、常量類
Arrays
Collections