Java原始碼分析——java.util工具包解析(一)——ArrayList、LinkedList、Vector類解析
Java中,List列表類與Set集合類的共同源頭是Collection介面,而Collection的父介面是Iterable介面,在Collection介面下又實現了三個常用的介面以及一個抽象方法,分別為Queue介面、List介面、Set介面以及AbstractCollection抽象類,它們之間的關係如圖:
而今天所講的AbstractList抽象類及其實現類則是繼承自AbstractCollection抽象類,在AbstractList抽象類中封裝了對ArrayList類與LinkedList類以及Vector類的共同操作,來給三者重寫,下面來分別談談其實現類的區別與注意事項,先上圖:
ArrayList
ArrayList類是列表的陣列表達形式,繼承了AbstracterList抽象類以及List介面、Clone介面以及序列化介面,其預設的到存貯大小是10:
private static final int DEFAULT_CAPACITY = 10;
而且每次容量不夠擴容時,是擴充套件到原來的1.5倍的,假如不夠的話直接採用要求的容量大小,並呼叫Arrays的陣列複製的方法來複制:
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//新的容量
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity) ;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
其實現的克隆方法是我們平常意義上的淺克隆,只是在堆區新建了空間用來一個新的ArrayList,但是並沒有新建空間來存放裡面的元素,裡面的元素還是指向的原來的地址,其原始碼如下:
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
通過以下程式碼驗證:
String s1=new String("1");
String s2=new String("1");
String s3=new String("1");
ArrayList<String> list=new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3);
ArrayList<String> list2=(ArrayList<String>)list.clone();
System.out.print(list2.get(0)==list.get(0));
//列印為true
LinkedList
LinkedList類是列表結構的鏈式表達方式,與ArrayList實現了相同的介面,它的內部節點的結構如下:
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;
}
}
很簡單的連結串列節點,也定義了first、last以及size來分別記錄頭結點、尾節點以及連結串列的節點大小:
transient int size = 0;
transient Node<E> first;
transient Node<E> last;
同時可以把LinkedList當做棧來使用,因為其方法裡含有這兩個方法:
public void push(E e) {
addFirst(e);
}
public E pop() {
return removeFirst();
}
也實現了佇列:
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
public E element() {
return getFirst();
}
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
push時從頭結點壓入,而pop時也從頭結點取出,也就是實現了棧的先進後出。與ArrayList一樣,LinkedList的克隆方法也是一個淺克隆。
Vector
Vector類相當於是ArrayList的執行緒安全實現,它在需要對元素進行修改的方法加了synchronized關鍵字,實現了執行緒安全,比如縮小容量:
public synchronized void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (elementCount < oldCapacity) {
elementData = Arrays.copyOf(elementData, elementCount);
}
}
但是Vector的擴容是與ArrayList不一樣的,Vector內部多了一個capacityIncrement成員變數,這個變數是由呼叫者傳進來的,可以讓程式設計師自己來定義,Vector每次擴容都會增加capacityIncrement大小:
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
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);
}
而Stack類是Vector的子類,在Vector類的基礎上實現了元素的先進後出,是一個執行緒安全類:
public class Stack<E> extends Vector<E> {
public E push(E item) {
// addElement是個同步方法
addElement(item);
return item;
}
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
}