Java:集合類性能分析

 1.Java 集合框架圖

Java:集合類性能分析

  -集合接口:6個接口(短虛線表示),表示不同集合類型,是集合框架的基礎。

  -抽象類:5個抽象類(長虛線表示),對集合接口的部分實現。可擴展爲自定義集合類。

  -實現類:8個實現類(實線表示),對接口的具體實現。

  2.Java容器類介紹

  ① Java容器類都可以自動地調整自己的尺寸。

  ② Collection 接口是一組允許重複的對象。

  ③ Set 接口繼承 Collection,不允許重複,使用自己內部的一個排列機制。

  ④ List 接口繼承 Collection,允許重複,以元素安插的次序來放置元素,不會重新排列。

  ⑤ Map接口是一組成對的鍵-值對象,即所持有的是key-value pairs。Map中不能有重複的key。擁有自己的內部排列機制。

  Java 2簡化集合框架圖

Java:集合類性能分析

  3.Collection接口

  基本操作

  -增加元素add(Object obj); addAll(Collection c);

  -刪除元素 remove(Object obj); removeAll(Collection c);

  -求交集 retainAll(Collection c);

  Collection是最基本的集合接口,所有實現Collection接口的類都必須提供兩個標準的構造函數:無參數的構造函數用於創建一個空的Collection,有一個 Collection參數的構造函數用於創建一個新的Collection,這個新的Collection與傳入的Collection有相同類型的元素。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class AddingGroups {
  public static void main(String[] args) {
    Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(
       1, 2, 3, 4, 5));
    Integer[] moreInts={6,7,8,9,10};
    collection.addAll(Arrays.asList(moreInts));
    for (Integer i : collection)
      System.out.print(i + ",");
  }
}

  結果:

  1,2,3,4,5,6,7,8,9,10,

 

  這裏展示了Collection接口的2個用法,首先,Collection構造函數接受另一個Collection(List)作爲參數,使其初始化。接着,調用addAll()方法添加元素,注意,該方法只接受另一個Collection作爲參數。

  此外,必須注意,Collection接口不提供隨機訪問元素的get()方法。因爲Collection包括Set,而Set自己維護內部順序。如果想檢查Collection中的元素,那就必須使用迭代器。

  4.List接口

  4.1 List接口

  List是有序的Collection,使用此接口能夠精確的控制每個元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似於數組下標)來訪問List中的元素,這類似於Java的數組。

  和下面要提到的Set不同,List允許有相同的元素。

  除了具有Collection接口必備的iterator()方法外,List還提供一個listIterator()方法,返回一個 ListIterator接口,和標準的Iterator接口相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設定元素, 還能向前或向後遍歷。

  4.2 LinkedList類

  LinkedList實現了List接口,允許null元素。此外LinkedList提供額外的get,remove,insert方法在 LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊列(queue)或雙向隊列(deque)。此實現不是同步的。

  4.3 ArrayList類

  ArrayList實現了可變大小的數組。它允許所有元素,包括null。

  size,isEmpty,get,set方法運行時間爲常數。但是add方法開銷爲分攤的常數,添加n個元素需要O(n)的時間。其他的方法運行時間爲線性。

  每個ArrayList實例都有一個容量(Capacity),即用於存儲元素的數組的大小。這個容量可隨着不斷添加新元素而自動增加,但是增長算法並沒有定義。當需要插入大量元素時,在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率。此實現不是同步的。

  5.Set接口

  5.1 Set接口

  Set具有和Collection完全一樣的接口,沒有任何額外的功能。它是一種不包含重複的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。

  很明顯,Set的構造函數有一個約束條件,傳入的Collection參數不能包含重複的元素。

  請注意:必須小心操作可變對象(Mutable Object)。如果一個Set中的可變元素改變了自身狀態導致Object.equals(Object)=true將導致一些問題。

  5.2 HashSet

  此類實現Set 接口,由哈希表(實際上是一個 HashMap 實例)支持。它不保證 set 的迭代順序;特別是它不保證該順序恆久不變。此類允許使用 null 元素。此類爲基本操作提供了穩定性能,此實現不是同步的。

  5.3 LinkedHashSet

  具有可預知迭代順序的Set 接口的哈希表和鏈接列表實現。此實現與HashSet的不同之處在於,它維護着一個運行於所有條目的雙重鏈接列表。此鏈接列表定義了迭代順序,即按照將元素插入到set中的順序(插入順序)進行迭代。注意,插入順序不受在set中重新插入的元素影響。此實現不是同步的。

  5.4 TreeSet

  基於TreeMap的NavigableSet實現。使用元素的自然順序對元素進行排序,或者根據創建set時提供的 Comparator 進行排序,具體取決於使用的構造方法。此實現爲基本操作(add、remove 和 contains)提供受保證的 log(n) 時間開銷。此實現不是同步的。

  6.Map接口

  請注意,Map沒有繼承Collection接口,Map提供key到value的映射。一個Map中不能包含相同的key,每個key只能映射一個 value。Map接口提供3種集合的視圖,Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射。

  6.1 WeakHashMap

  以弱鍵實現的基於哈希表的Map。在WeakHashMap中,當某個鍵不再正常使用時,將自動移除其條目。更精確地說,對於一個給定的鍵,其映射的存在並不阻止垃圾回收器對該鍵的丟棄,這就使該鍵成爲可終止的,被終止,然後被回收。丟棄某個鍵時,其條目從映射中有效地移除,因此,該類的行爲與其他的Map實現有所不同。此實現不是同步的。

  6.2 TreeMap

  該映射根據其鍵的自然順序進行排序,或者根據創建映射時提供的Comparator進行排序,具體取決於使用的構造方法。此實現不是同步的。

  6.3 HashMap

  基於哈希表的Map接口的實現。此實現提供所有可選的映射操作,並允許使用 null 值和 null 鍵。(除了非同步和允許使用null之外,HashMap 類與 Hashtable 大致相同。)此類不保證映射的順序,特別是它不保證該順序恆久不變。此實現不是同步的。

  6.4 SortedMap

  進一步提供關於鍵的總體排序的Map。該映射是根據其鍵的自然順序進行排序的,或者根據通常在創建有序映射時提供的Comparator進行排序。對有序映射的collection 視圖(由 entrySet、keySet 和 values 方法返回)進行迭代時,此順序就會反映出來。要採用此排序方式,還需要提供一些其他操作(此接口是 SortedSet 的對應映射)。

  7.集合類性能效率總結

  注意,這裏展示的類都是非線程安全的。如果需要考慮線程安全,應該使用ConcurrentMap,CopyOnWriteArrayList,CopyOnWriteArraySet等。

  總結

  ①如果涉及到堆棧,隊列等操作,應該考慮用List。如果要進行大量的隨機訪問,應使用ArrayList;如果經常進行插入與刪除操作,用使用LinkedList。

  ②HashMap設計用來快速訪問;而TreeMap保持“鍵”始終處於排序狀態,所以沒有HashMap快。LinkedHashMap保持元素插入的順序,但是也通過散列提供了快速訪問能力。

  ③Set不接受重複元素。HashSet提供最快的查詢速度,而TreeSet保持元素處於排序狀態。LinkedHashSet以插入順序保存元素。

  ④對哈希表的操作,作爲key的對象要正確重寫equals和hashCode方法。

  ⑤儘量返回接口而非實際的類型(針對抽象編程),如返回List而非ArrayList,這樣如果以後需要將ArrayList換成LinkedList時,客戶端代碼不用改變。

  ⑥程序中不應該使用過時的VectorHashtableStack。

  本文出自 “子 孑” 博客,請務必保留此出處http://zhangjunhd.blog.51cto.com/113473/69677

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