說明
- Java版本:1.8.0_231
ArrayList
- 底層由Object數組實現,具有數組的所有特性,實現了
RandomAccess
接口支持隨機訪問,非線程安全類型
Object[] elementData;
- 構造方法
- 創建一個空數組
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
- 具有初試容量的數組
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
- add()方法及擴容機制
public boolean add(E e) {
ensureCapacityInternal(size + 1);
// 將元素e添加到末尾
elementData[size++] = e;
return true;
}
- 數組容量初始化
private static int calculateCapacity(Object[] elementData, int minCapacity) {
// 判斷是否是爲空數組,若爲空,返回10;否則將返回arr.length + 1(第一次添加數據肯定是空的,第二次及後續就是arr.length +1)
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
- 判斷是否到達擴容零界點
private void ensureExplicitCapacity(int minCapacity) {
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// 核心 開始擴容
private void grow(int minCapacity) {
// 獲取數組長度
int oldCapacity = elementData.length;
// 右移位運算得出擴容後的長度
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 將擴容後的數據賦值給原數組
elementData = Arrays.copyOf(elementData, newCapacity);
}
在添加第一個元素時,就會調用grow()
方法進行擴容操作,但此時數組長度爲0,擴容後的
LinkedList
- 底層由雙向鏈表實現,實現了
Deque
接口,可以雙向操作,不支持隨機訪問,非線程安全類型
// node節點
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;
}
}
// 指向上一個節點
Node<E> first;
// 指向下一個節點
Node<E> last;
- 兩個構造函數
- 構造一個空List
public LinkedList() {
}
- 一個有參構造函數
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}sdss
- 鏈表追加節點至末尾
public boolean add(E e) {
linkLast(e);
return true;
}
// 這個就不解釋,應該懂得
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
Vector
- 底層有Object數組實現,實現了
RandomAccess
接口,支持隨機訪問,線程安全類型
protected Object[] elementData;
- 三個構造函數(其實是一個)
- 賦予初始容量和擴容量
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
- 使用默認的擴容量0
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
- 使用默認的初始容量10和初始容量0
public Vector() {
this(10);
}
- 添加元素與擴容機制
public synchronized void addElement(E obj) {
// 擴容
ensureCapacityHelper(elementCount + 1);
// 將新增元素添加到數組末尾
elementData[elementCount++] = obj;
}
private void ensureCapacityHelper(int minCapacity) {
// 第一次添加元素時,minCapacity=10,elementData.length = 0,這時不會進行擴容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// 獲取數據的長度
int oldCapacity = elementData.length;
// 擴容核心:在創建數組時指定了capacityIncrement且大於0,擴容後的值爲capacityIncrement+初始容量,反之爲初始容量+初始容量,即兩倍的初始容量
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
List接口主要實現類總結
- ArrayList和Vector底層基於數組實現,具有數組的所有特性且支持隨機訪問,其中Vector時線程安全的;在擴容機制上:
- ArrayList是1.5倍擴容,關鍵代碼爲
int newCapacity = oldCapacity + (oldCapacity >> 1);
即 10 --> 15; - Vector是2倍擴容,關鍵代碼:
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
,即:10 --> 20
- LinkedList是基於雙向鏈表實現,可雙向插入,插入刪除快,查找慢
網站原文:https://www.haicheng.website/passages/source-code-analysis-01/