Java容器類型使用總結

jopen 9年前發布 | 19K 次閱讀 Java Java開發

最近抽空把java.lang下面常用的那些容器類型(數據結構)復習了一下,這些東西是基礎,平時使用的時候也可以很容易查得到,有些方法大概知 道,但是總是弄混,如果可以記住那些重要方法,并且能夠熟練使用的話,還是可以讓編碼過程變得容易很多。另外一個是實現機制,對于常用數據結構的實現機 制,應該說是必須要熟知的。

另外,并發容器我之前整理過,放在這篇文章里。

Queue

  1. add和offer的區別在于達到上限時add拋出異常,offer返回false;
  2. remove和poll的區別在于,隊列為空時前者拋出異常,后者返回空;
  3. element和peek都返回隊列頭部元素,但是前者失敗不拋出異常,后者返回空。
  4. </ol>

    boolean add(E e);
    boolean offer(E e);

    E remove(); E poll();

    E element(); E peek();</pre>

    PriorityQueue,內部實現是一個Object[] queue承載的堆。

    Deque,雙端隊列(double-ended queue),在Queue基礎上,增加了這樣幾個方法:

    void addFirst(E e);
    void addLast(E e);

    boolean offerFirst(E e); boolean offerLast(E e);

    E removeFirst(); E removeLast();

    E pollFirst(); E pollLast();

    E getFirst(); E getLast();

    E peekFirst(); E peekLast();

    boolean removeFirstOccurrence(Object o); boolean removeLastOccurrence(Object o);</pre>

    ArrayDequeue:數組實現,擴容策略是容量翻倍。

    List

    boolean add(E e);
    boolean remove(Object o);
    E get(int index);
    E set(int index, E element);
    void add(int index, E element);
    E remove(int index);

    ArrayList,擴容策略是(oldCapacity * 3)/2 + 1。

    LinkedList,它除了實現自List接口外,還實現了Deque接口。

    Vector,實現自List接口,內部實現是個數組,線程安全,擴容策略是(capacityIncrement > 0) ? (oldCapacity + capacityIncrement) : (oldCapacity * 2)。

    Stack是Vector的子類,增加了一些棧的方法:

    E push(E item)
    E pop()
    E peek()
    boolean empty()

    Map

    boolean containsKey(Object key);
    boolean containsValue(Object value);

    V get(Object key); V put(K key, V value); V remove(Object key);

    Set<K> keySet(); Collection<V> values(); Set<Map.Entry<K, V>> entrySet();</pre>

    SotedMap接口,key是有序的map:

    SortedMap<K, V> subMap(K paramK1, K paramK2);
    SortedMap<K, V> headMap(K paramK);
    SortedMap<K, V> tailMap(K paramK);

    K firstKey(); K lastKey();</pre>

    子接口NavigableMap,提供了一些根據某個key尋找它前面或者后面的key的方法。其中floorKey/celingKey表示的關系是小于等于/大于等于,lower/higher表示的關系是嚴格的小于/大于:

    Map.Entry<K,V> floorEntry(K key)
    K floorKey(K key)
    Map.Entry<K,V> ceilingEntry(K key)
    K ceilingKey(K key)

    Map.Entry<K,V> lowerEntry(K key) K lowerKey(K key) Map.Entry<K,V> higherEntry(K key) K higherKey(K key)</pre>

    TreeMap是NavigableMap的直接實現子類,內部實現是一個紅黑樹。

    EnumMap,結構是<K extends Enum<K>, V>,內部是通過一個K[] keyUniverse和一個Object[] vals來實現的。

    HashMap,內部是數組+鏈表實現的,達到threshold = capacity * loadFactor時,擴容策略為:numKeysToBeAdded / loadFactor + 1。

    HashTable,實現自Dictionary和Map,方法都是 線程安全的。HashTable的put方法,value不可以為空,這是它和HashMap的一個不同;再有二者找桶的hash方法不同;最后則是 threshold計算邏輯相同,但它的擴容策略不同:oldCapacity * 2 + 1。HashTable、HashMap和HashSet經常被放到一起比較。

    Properties,是HashTable的子類,方法線程安全。

    IdentityHashMap,比較key不是使用equals來比較,而是使用“==”來比較,只要地址不等(即不是同一個對象)即可共存,也就是說,key是可以重復的。

    LinkedHashMap,在HashMap的基礎上,又單獨維護 了一個雙向循環鏈表。有一個重要參數是accessOrder,accessOrder為true時,每次調用get方法訪問行為發生后,會把最近訪問的 對象移動到頭部,而超出容量移除對象時,是從尾部開始的,利用它并且覆寫boolean removeEldestEntry方法可以實現一個LRU的隊列。

    WeakHashMap,但是key是weak引用,在不被使用時自 動清除,擴容策略:tab.length * 2。原理上看:Entry<K,V> extends WeakReference<K> implements Map.Entry<K,V>,因此entry是弱引用的實現類,關鍵方法是expungeStaleEntries,它在對這個map各種 操作的時候都會被調用到,而這個方法里面也是靠監聽key的ReferenceQueue這個隊列的狀態來確定是否真的沒有對象引用了。

    Set

    boolean contains(Object o);
    boolean add(E e);
    boolean remove(Object o);

    SortedSet,接口方法和SortedMap類似:

    SortedSet<E> subSet(E fromElement, E toElement);
    SortedSet<E> headSet(E toElement);
    SortedSet<E> tailSet(E fromElement);

    E first(); E last();</pre>

    相應地,NavigableSet和NavigableMap類似,方法就不列出了。

    TreeSet則和TreeMap類似,其實內部實現就是一個TreeMap。

    HashSet,尤其注意的是,有兩種實現,當構造方法參數小于3個時,內部使用HashMap,否則,使用LinkedHashMap。

    RegularEnumSetJumboEnumSet,前者是普通的枚舉set(用位移來表示各種組合的可能,達到空間占用最小,最大不能超過64個枚舉值),后者適合數量較大的枚舉set(老老實實地使用對象數組)。

    LinkedHashSet,其實和LinkedHashMap是一個東西。

    BitSet,叫set但是沒有實現set的接口。用比特位來存放某個數是否存在,比如僅僅一個long,64位,就可以存放0~63的數,內部實際的數據類型是long[]。

    void flip(int bitIndex);
    void flip(int fromIndex, int toIndex);

    void set(int bitIndex); void set(int fromIndex, int toIndex, boolean value);

    void clear(int bitIndex);

    int length(); int size();</pre>

    其中size方法返回實際使用了的比特位數目;length方法返回邏輯意義上的長度(比如表示的數里面最大是80,那么加上0,它的邏輯意義上的長度就是81)。

    擴容策略:Math.max(2 * words.length, wordsRequired)。

    Dictionary

    Enumeration<K> keys();
    Enumeration<V> elements();

    V get(Object key); V put(K key, V value); V remove(Object key);</pre>

    已經被廢棄了,用Map來實現相同功能。

    最后這張圖來自這個網站,對于從宏觀上把握這些容器類型實在是太有幫助了:

    Java容器類型使用總結

    來源:四火的嘮叨

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!