採用Object
數組存儲元素node
protected Object[] elementData;
Stack
繼承了Vector
,採用Object
數組存儲元素數組
顧名思義,ArrayList
底層採用數組存儲元素數據結構
Object[] elementData;
顧名思義,LinkedList
底層採用鏈表存儲元素。經過first
和last
指針分別指向頭元素和尾元素。併發
/** * Pointer to first node. * Invariant: (first == null && last == null) || * (first.prev == null && first.item != null) */ transient Node<E> first; /** * Pointer to last node. * Invariant: (first == null && last == null) || * (last.next == null && last.item != null) */ transient Node<E> last;
其中Node
是LinkedList
自定義的靜態類,經過next
和prev
指針分別指向後驅節點和前驅節點。所以LinkedList
底層是經過first
和last
指針分別指向頭元素和尾元素的雙向鏈表。函數
private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }
顧名思義,CopyOnWriteArrayList
底層是經過Object[]
數組存儲數據,提供的構造方法在初始化時自動建立了長度爲0
的數組。ui
/** The array, accessed only via getArray/setArray. */ private transient volatile Object[] array; /** * Creates an empty list. */ public CopyOnWriteArrayList() { setArray(new Object[0]); }
CopyOnWrite
的邏輯大致上都是在插入數據的時候,從新複製一份數組,在新數組中插入新數據,以後將指針指向新的數組。這種模式主要是爲了針對「改動操做不多,主要是讀操做」的業務。CopyOnWriteArrayList
同樣,在操做數據時經過ReentrantLock
鎖住防止併發以後,複製原數組再在新數組中操做數據,最後將指針指向新數組。this
public E set(int index, E element) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); E oldValue = get(elements, index); if (oldValue != element) { int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len); newElements[index] = element; setArray(newElements); } else { // Not quite a no-op; ensures volatile write semantics setArray(elements); } return oldValue; } finally { lock.unlock(); } } public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } } public E remove(int index) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; E oldValue = get(elements, index); int numMoved = len - index - 1; if (numMoved == 0) setArray(Arrays.copyOf(elements, len - 1)); else { Object[] newElements = new Object[len - 1]; System.arraycopy(elements, 0, newElements, 0, index); System.arraycopy(elements, index + 1, newElements, index, numMoved); setArray(newElements); } return oldValue; } finally { lock.unlock(); } }
HashTable
底層經過Entry
數組存儲元素,spa
private transient Entry<?,?>[] table;
Entry
類型爲HashTable
自定義的數據結構,內部記錄了元素的hash
值,key
,value
,以及下一節點的指針next
。private static class Entry<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Entry<K,V> next; protected Entry(int hash, K key, V value, Entry<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } @SuppressWarnings("unchecked") protected Object clone() { return new Entry<>(hash, key, value, (next==null ? null : (Entry<K,V>) next.clone())); } // Map.Entry Ops public K getKey() { return key; } public V getValue() { return value; } public V setValue(V value) { if (value == null) throw new NullPointerException(); V oldValue = this.value; this.value = value; return oldValue; } public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<?,?> e = (Map.Entry<?,?>)o; return (key==null ? e.getKey()==null : key.equals(e.getKey())) && (value==null ? e.getValue()==null : value.equals(e.getValue())); } public int hashCode() { return hash ^ Objects.hashCode(value); } public String toString() { return key.toString()+"="+value.toString(); } }
HashMap
底層經過 Node
數組存儲元素線程
transient Node<K,V>[] table;
Node
是HashMap
自定義的數據結構,內部記錄了元素的hash
值,key
,value
,以及下一節點的指針next
。static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Node<K,V> next; Node(int hash, K key, V value, Node<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } public final K getKey() { return key; } public final V getValue() { return value; } public final String toString() { return key + "=" + value; } public final int hashCode() { return Objects.hashCode(key) ^ Objects.hashCode(value); } public final V setValue(V newValue) { V oldValue = value; value = newValue; return oldValue; } public final boolean equals(Object o) { if (o == this) return true; if (o instanceof Map.Entry) { Map.Entry<?,?> e = (Map.Entry<?,?>)o; if (Objects.equals(key, e.getKey()) && Objects.equals(value, e.getValue())) return true; } return false; } }
當元素hash
相同時,元素會經過鏈表的形式經過next
指針相連。在JDK1.8
以後,當知足必定條件後,鏈表會轉化爲紅黑樹,此時,元素會從Node
類型轉化爲TreeNode
類型。3d
TreeNode
爲HashMap
自定義的數據結構,內部記錄父節點parent
,左右孩子left
,right
,顏色標誌red
已經同級前驅節點prev
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> { TreeNode<K,V> parent; // red-black tree links TreeNode<K,V> left; TreeNode<K,V> right; TreeNode<K,V> prev; // needed to unlink next upon deletion boolean red; TreeNode(int hash, K key, V val, Node<K,V> next) { super(hash, key, val, next); } ...... }
具體的操做邏輯能夠參考:[[HashMap]]
LinkedHashMap
繼承了HashMap
的邏輯,只不過添加了Entry
結構。以及head
,tail
首尾指針。
static class Entry<K,V> extends HashMap.Node<K,V> { Entry<K,V> before, after; Entry(int hash, K key, V value, Node<K,V> next) { super(hash, key, value, next); } } private static final long serialVersionUID = 3801124242820219131L; /** * The head (eldest) of the doubly linked list. */ transient LinkedHashMap.Entry<K,V> head; /** * The tail (youngest) of the doubly linked list. */ transient LinkedHashMap.Entry<K,V> tail;
Entry
中保存了before
和after
指針,指向上一個插入元素Entry
以及後一個插入元素Entry
。以數組+紅黑樹+元素鏈表+插入順序鏈表的形式存儲數據。
ConcurrentHashMap
底層經過Node
數組存儲數據
transient volatile Node<K,V>[] table;
Node
是ConcurrentHashMap
自定義的數據結構,內部記錄了元素的hash
值,key
,value
,以及下一節點的指針next
。static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; volatile V val; volatile Node<K,V> next; Node(int hash, K key, V val, Node<K,V> next) { this.hash = hash; this.key = key; this.val = val; this.next = next; } public final K getKey() { return key; } public final V getValue() { return val; } public final int hashCode() { return key.hashCode() ^ val.hashCode(); } public final String toString(){ return key + "=" + val; } public final V setValue(V value) { throw new UnsupportedOperationException(); } public final boolean equals(Object o) { Object k, v, u; Map.Entry<?,?> e; return ((o instanceof Map.Entry) && (k = (e = (Map.Entry<?,?>)o).getKey()) != null && (v = e.getValue()) != null && (k == key || k.equals(key)) && (v == (u = val) || v.equals(u))); } /** * Virtualized support for map.get(); overridden in subclasses. */ Node<K,V> find(int h, Object k) { Node<K,V> e = this; if (k != null) { do { K ek; if (e.hash == h && ((ek = e.key) == k || (ek != null && k.equals(ek)))) return e; } while ((e = e.next) != null); } return null; } }
當元素hash
相同時,元素會經過鏈表的形式經過next
指針相連。在JDK1.8
以後,當知足必定條件後,鏈表會轉化爲紅黑樹,此時,table數組中的Node 元素會轉化爲TreeBin類型,TreeBin類型記錄了由TreeNode構成紅黑樹的根節點root。
TreeBin
有ConcurrentHashMap
自定義,繼承了Node
類型。存放了下轄紅黑樹的根節點root
。static final class TreeBin<K,V> extends Node<K,V> { TreeNode<K,V> root; volatile TreeNode<K,V> first; volatile Thread waiter; volatile int lockState; // values for lockState static final int WRITER = 1; // set while holding write lock static final int WAITER = 2; // set when waiting for write lock static final int READER = 4; // increment value for setting read lock ...... }
TreeNode
由ConcurrentHashMap
自定義,跟HashMap
的TreeNode
相似,可是ConcurrentHashMap
的TreeNode
繼承自Node
類型。static final class TreeNode<K,V> extends Node<K,V> { TreeNode<K,V> parent; // red-black tree links TreeNode<K,V> left; TreeNode<K,V> right; TreeNode<K,V> prev; // needed to unlink next upon deletion boolean red; TreeNode(int hash, K key, V val, Node<K,V> next, TreeNode<K,V> parent) { super(hash, key, val, next); this.parent = parent; } ...... }
具體的操做邏輯能夠參考:[[ConcurrentHashMap]]
TreeMap
經過Entry
存儲數據,底層是以紅黑樹的邏輯結構存儲。
private transient Entry<K,V> root;
Entry
是TreeMap
自定義的數據結構,其中包含key
,value
,左右子樹left
,right
,以及父節點parent
,和標記顏色的color
;static final class Entry<K,V> implements Map.Entry<K,V> { K key; V value; Entry<K,V> left; Entry<K,V> right; Entry<K,V> parent; boolean color = BLACK; /** * Make a new cell with given key, value, and parent, and with * {@code null} child links, and BLACK color. */ Entry(K key, V value, Entry<K,V> parent) { this.key = key; this.value = value; this.parent = parent; } ...... }
WeakHashMap
底層經過Entry[]
數組存儲數據,採用鏈表法解決hash
衝突,跟HashMap
不一樣沒有進行長鏈表的紅黑樹轉化。
Entry<K,V>[] table;
Entry
爲WeakHashMap
自定義的數據結構繼承了WeakReference
,其中包含value
,hash
值,以及next
指針。key
爲弱引用reference
的值。private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> { V value; final int hash; Entry<K,V> next; /** * Creates new entry. */ Entry(Object key, V value, ReferenceQueue<Object> queue, int hash, Entry<K,V> next) { super(key, queue); this.value = value; this.hash = hash; this.next = next; } ...... }
具體的操做邏輯能夠參考:[[WeakHashMap]]
ConcurrentSkipListMap
底層經過跳錶的數據結構提升查找效率。ConcurrentSkipListMap
經過Node
存儲基本的key
,value
數據,Index
存儲跳錶索引,HeadIndex
爲層級頭索引。
// Node存儲基本的key,value數據,是一個簡單的鏈表 static final class Node<K,V> { final K key; volatile Object value; volatile Node<K,V> next; ... } // Index 內包含Node元素,以及向下和向右的Index指針 static class Index<K,V> { final Node<K,V> node; final Index<K,V> down; volatile Index<K,V> right; ... } // HeadIndex繼承了Index,添加了level索引層級屬性 static final class HeadIndex<K,V> extends Index<K,V> { final int level; HeadIndex(Node<K,V> node, Index<K,V> down, Index<K,V> right, int level) { super(node, down, right); this.level = level; } }
同時,ConcurrentSkipListMap
經過對大部分操做添加CAS
鎖防止併發。
HashSet
底層默認經過HashMap
存儲元素,數據儲存在HashMap
的key
中,value
設置爲默認值Object
。
private transient HashMap<E,Object> map; private static final Object PRESENT = new Object(); // default value public boolean add(E e) { return map.put(e, PRESENT)==null; }
HashSet
底層還能夠經過 LinkedHashMap
存儲元素。根據構造函數參數不一樣選擇是 HashMap
仍是LinkedHashMap
實現。
HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<>(initialCapacity, loadFactor); }
LinkedhashSet
繼承了HashSet
,採用LinkedHashMap
存儲元素。
底層經過ConcurrentSkipListMap
實現,存放的值做爲key
存入ConcurrentSkipListMap
中,使用Boolean.TRUE
對象最爲默認的value
。
private final ConcurrentNavigableMap<E,Object> m; /** * Constructs a new, empty set that orders its elements according to * their {@linkplain Comparable natural ordering}. */ public ConcurrentSkipListSet() { m = new ConcurrentSkipListMap<E,Object>(); } public boolean add(E e) { return m.putIfAbsent(e, Boolean.TRUE) == null; }
TreeSet
底層經過TreeMap
存儲元素,和HashSet
相似,數據存儲在TreeMap
的Key
中,value
設置爲默認值Object
。
private transient NavigableMap<E,Object> m; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); }
底層經過CopyOnWriteArrayList
實現,經過List.addIfAbsent()
方法實現同一個元素只存在一個,保證了元素的惟一性。
private final CopyOnWriteArrayList<E> al; /** * Creates an empty set. */ public CopyOnWriteArraySet() { al = new CopyOnWriteArrayList<E>(); } public boolean add(E e) { return al.addIfAbsent(e); }
PriorityQueue
優先隊列,底層經過Object
數組存儲元素,Object[]
以層次遍歷的形式存儲優先隊列(徹底二叉樹)的元素值。索引n的左右孩子索引分別爲$2n+1,2*(n+1)$;
transient Object[] queue;
A Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.
阻塞隊列接口,提供了額外的一些操做,當這些操做沒法當即執行時(插入時容量滿了、刪除/獲取元素時隊列爲空),不會像正常的queue一些當即返回而是阻塞一段時間直到知足條件(設置了等待時間、條件知足了)
阻塞隊列的阻塞操做通常是經過建立多個條件鎖ReentrantLock.Condition
實現的,經過調用Condition.await()
以及Condition.signal()
進行線程的阻塞和喚醒。
private final Condition notEmpty; /** Condition for waiting puts */ private final Condition notFull;
添加元素
add(E e)/offer(E e)
方法,當數組滿了以後,直接返回false
public boolean offer(E e) { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lock(); try { if (count == items.length) return false; else { enqueue(e); return true; } } finally { lock.unlock(); } }
put(E e)/offer(E e, long timeout, TimeUnit unit)
方法,當數組滿了以後,阻塞直到喚醒或者阻塞指定時間
public void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) notFull.await(); enqueue(e); } finally { lock.unlock(); } } public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException { checkNotNull(e); long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) { if (nanos <= 0) return false; nanos = notFull.awaitNanos(nanos); } enqueue(e); return true; } finally { lock.unlock(); } }
獲取元素
poll()
,彈出隊首元素,隊列爲空時直接return null;
take()
,彈出隊首元素,隊列爲空時阻塞至隊列不爲空。poll(long timeout, TimeUnit unit)
,彈出隊首元素,隊列爲空時阻塞指定時間後重試一次。peek()
,獲取隊首元素,隊列爲空時直接return null;
A bounded BlockingQueue backed by an array. This queue orders elements FIFO (first-in-first-out). The head of the queue is that element that has been on the queue the longest time. The tail of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue.
顧名思義,ArrayBlockingQueue
底層是經過Object[]
數組實現元素的存儲的。ArrayBlockingQueue
是有界隊列,存儲元素的數量經過初始化方法指定。當數組滿了的時候,就沒法直接往數組中添加元素了。ArrayBlockingQueue
FIFO,添加元素到隊尾,刪除隊首元素。
初始化方法
public ArrayBlockingQueue(int capacity, boolean fair) { if (capacity <= 0) throw new IllegalArgumentException(); this.items = new Object[capacity]; lock = new ReentrantLock(fair); notEmpty = lock.newCondition(); notFull = lock.newCondition(); }
根據初始化參數動態構造是否有界的阻塞隊列。底層經過Node
結構實現的鏈表進行存儲。
Node結構
static class Node<E> { E item; Node<E> next; Node(E x) { item = x; } }
初始化方法
public LinkedBlockingQueue() { // 不指定隊列容量,默認爲Integer的最大值 this(Integer.MAX_VALUE); } public LinkedBlockingQueue(int capacity) { if (capacity <= 0) throw new IllegalArgumentException(); this.capacity = capacity; last = head = new Node<E>(null); }
ArrayBlockingQueue
和LinkedBlockingQueue
除了底層實現方式不一樣以外,ArrayBlockingQueue
在進行數據操做時用的都是同一把鎖final ReentrantLock lock;
,而LinkedBlockingQueue
初始化了二把鎖插入和彈出操做使用不一樣的鎖。final ReentrantLock putLock; final ReentrantLock takeLock;