Java 集合類

1 List

  1.1 ArrayList

      基於數組實現,按照插入順序排序可重複,線程不安全,默認初始化爲空數組對象,在添加第一個元素時,初始化大小爲10的數組。支持自動擴容,擴展因子爲0.5,即 newCapacity=oldCapacity*1.5,擴容方式是 Arrays.copyOf(elementData, newCapacity);。
算法

  1.2 Vector

     基於數組實現,按照插入順序排序可重複,經過 synchronized 來保證線程安全,默認初始化大小爲10的數組。添加元素時。支持自動擴容,擴展因子爲1,即 newCapacity=oldCapacity*2,擴容方式是 Arrays.copyOf(elementData, newCapacity);。數組

  1.3 LinkedList

      基於雙向鏈表實現,按照插入順序排序,實現了接口 Deque,因此它也是一個雙端隊列安全

1 // 雙端鏈表結構 
2 private static class Node<E> { 
3     E item; Node<E> next; Node<E> prev; 
4 }
View Code

2 Map

  2.1 HashMap

      基於散列鏈表+紅黑樹實現,無序,鏈表長度>=8時轉爲紅黑樹,紅黑樹<=6時轉爲鏈表,首次添加元素時,初始化默認數組長度16,而且必須是2的冪次方大小,當指定的大小不夠2的冪次方時自動補齊大小,默認加載因子0.75,默認擴展因子1,線程不安全併發

 1 // 哈希鏈表結構
 2 static class Node<K,V> implements Map.Entry<K,V> {
 3     final int hash; // 數組索引
 4     final K key;
 5     V value;
 6     Node<K,V> next; // 下一個節點
 7 }
 8 // 紅黑樹結構
 9 static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
10     TreeNode<K,V> parent;
11     TreeNode<K,V> left;
12     TreeNode<K,V> right;
13     TreeNode<K,V> prev;
14     boolean red;
15 }
View Code

      添加元素時爲了更均勻地分佈,對 key 進行兩次的 hash 運算。ide

1 static final int hash(Object key) {
2     int h;
3     return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
4 }
View Code

      擴容方式:resize(),擴容後的容量是以前的2倍spa

 1 Node<K,V> loHead = null, loTail = null;
 2 Node<K,V> hiHead = null, hiTail = null;
 3 Node<K,V> next;
 4 do {
 5     next = e.next;
 6     if ((e.hash & oldCap) == 0) { // 索引沒有變化
 7         if (loTail == null)
 8             loHead = e;
 9         else
10             loTail.next = e;
11         loTail = e;
12     }
13     else { // 索引變爲原索引+oldCap
14         if (hiTail == null)
15             hiHead = e;
16         else
17             hiTail.next = e;
18         hiTail = e;
19     }
20 } while ((e = next) != null);
21 if (loTail != null) {
22     loTail.next = null;
23     newTab[j] = loHead;
24 }
25 if (hiTail != null) {
26     hiTail.next = null;
27     newTab[j + oldCap] = hiHead;
28 }
View Code

      線程安全性問題線程

      一、put 致使數據丟失;code

      二、resize 致使的 get 操做時的死循環,JDK 8 已經解決此問題,利用 head 和 tail 來保證鏈表的順序不變,避免致使死循環;對象

  2.2 HashTable

      基於散列鏈表實現,默認數組長度11,默認加載因子0.75,默認擴展2*原數組長度+1,利用 synchronized 保證線程安全
blog

  2.3 TreeMap

      基於紅黑樹實現,按 key 天然排序。key 不等於 null。

  2.4 LinkedHashMap

      利用 HashMap 來實現。散列雙向鏈表的結構。

1 static class Entry<K,V> extends HashMap.Node<K,V> {
2     Entry<K,V> before, after;
3 }
View Code

      accessOrder 的排序方式:

  • accessOrder=false(默認)表示按插入順序排序
  • accessOrder=true 表示按訪問順序排序(最少被訪問的靠前,最近訪問的靠後),可用於實現LRU算法(Least recently used,最近最少使用算法)

3 Set

  3.1 HashSet

      利用 HashMap 實現,無序去重,默認初始化爲默認的 HashMap,value 固定爲 Object 對象,能夠參考 HashMap 的實現。

1 // 初始化
2 public HashSet() {
3     map = new HashMap<>();
4 }
5 // 添加元素
6 public boolean add(E e) {
7     return map.put(e, PRESENT)==null;
8 }
View Code

  3.2 TreeSet

      利用 TreeMap 實現,天然排序去重,不能添加 null,默認初始化爲默認的 TreeMap,value 固定爲 Object 對象,能夠參考 TreeMap 的實現。

  3.3 LinkedHashSet

      繼承了 HashSet,利用 LinkedHashMap 實現,能夠參考 LinkedHashMap 的實現。

4 Stack

      棧的結構,繼承了 Vector 類,利用 synchronized 來保證線程安全

5 Queue / Deque

      隊列 / 雙端隊列的結構,Deque 繼承 Queue 接口。

      常見實現:

  • PriorityQueue,優先隊列,默認初始化長度爲 11,經過二叉小頂堆實現,保證每次取出值最小的元素
  • ArrayDeque,數組實現的雙端隊列,默認初始化長度爲 16FIFO 原則。
  • LinkedList
  • BlockingQueue,阻塞隊列,詳見《併發集合包》。
相關文章
相關標籤/搜索