在 Java 集合框架中,List 介面定義了有序集合的標準行為,允許重複元素並支援索引存取。其兩大經典實現類 ArrayList 與 Vector 雖然底層皆以動態陣列(Object[] elementData)儲存資料,但在執行緒安全性與效能上有顯著差異。
ArrayList 內部維護兩個關鍵欄位:
Object[] elementData:實際儲存元素的陣列int size:目前集合中元素的實際數量預設建構子初始容量為 10,若指定初始容量則直接配置對應大小陣列。新增元素時會呼叫 ensureCapacity 確保空間足夠,擴容策略為 newCapacity = (oldCapacity * 3) / 2 + 1。值得注意的是,ArrayList 非執行緒安全,多執行緒環境下需外部同步或使用 Collections.synchronizedList 包裝。
Vector 的方法均以 synchronized 修飾,保證執行緒安全。但這也意味著單執行緒場景下,ArrayList 效能更優。若元素數量固定,直接使用陣列效率最高。
public class ListDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
String[] strArr = new String[3];
boolean ret = list.add("haha");
list.add(new String("aa"));
list.add(null);
System.out.println(list.size()); // 3
System.out.println(ret); // true
System.out.println(list); // [haha, aa, null]
System.out.println(strArr); // [LJava.lang.String;@1fee6fc
System.out.println(strArr.getClass().getName()); // [LJava.lang.String;
System.out.println(list.indexOf("aa")); // 1
System.out.println(list.indexOf(null)); // 2
String str = list.set(1, "ee");
System.out.println(str); // aa
System.out.println(list); // [haha, ee, null]
String remove = list.remove(0);
System.out.println(remove); // haha
System.out.println(list); // [ee, null]
boolean result = list.remove("ff");
System.out.println(result); // false
result = list.remove("ee");
System.out.println(result); // true
System.out.println(list); // [null]
}
}
public ArrayList() {
this(10);
}
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
this.elementData = new Object[initialCapacity];
}
public boolean add(E e) {
ensureCapacity(size + 1);
elementData[size++] = e;
return true;
}
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3) / 2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index + 1, elementData, index, numMoved);
elementData[--size] = null; // 釋放最後位置引用,利於 GC 回收
return oldValue;
}
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i] == null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
public E set(int index, E element) {
rangeCheck(index);
E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}
public E get(int index) {
rangeCheck(index);
return (E) elementData[index];
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
public void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (size < oldCapacity)
elementData = Arrays.copyOf(elementData, size);
}
理解 ArrayList 與 Vector 的底層實現,有助於根據場景選擇適當集合類:單執行緒首選 ArrayList,多執行緒需同步則考慮 Vector 或同步包裝器。掌握擴容、刪除位移等細節,能寫出更高效、健壯的程式碼。