ArrayList和Vector都屬於集合類,兩者內部都是用數組來實現的,區別在於前者不是線程安全的;而後者是線程安全的,其對外提供的大部分方法都用了synchronized修飾,所以性能會差些。
今天的重點是分析這兩者擴容的區別。
1、首先看ArrayList,在Java的JDK和Android的SDK中都有這個類,它們的擴容算法還有些細小區別。
1.1、Java(JDK1.7)中的ArrayList,數組默認大小爲10,
private static final int DEFAULT_CAPACITY = 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) {
ensureCapacityInternal(size + 1); // size爲當前數組內元素個數
elementData[size++] = e;
return true;
}
數組長度不夠,最後會調到這個函數:
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);
}
擴容規則就是 int newCapacity = oldCapacity + (oldCapacity >> 1);
其中 “ >> 1 ”相當於除以2,所以擴容後數組大小爲之前的1.5倍。
1.2、Android(SDK17)中的ArrayList,數組默認大小爲12,
private static final int MIN_CAPACITY_INCREMENT = 12;
也可以自己初始化數組大小
public ArrayList(int capacity) {
if (capacity < 0) {
throw new IllegalArgumentException();
}
array = (capacity == 0 ? EmptyArray.OBJECT : new Object[capacity]);
}
添加元素:
@Override public boolean add(E object) {
Object[] a = array;
int s = size;
if (s == a.length) {
Object[] newArray = new Object[s +
(s < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : s >> 1)];
System.arraycopy(a, 0, newArray, 0, s);
array = a = newArray;
}
a[s] = object;
size = s + 1;
modCount++;
return true;
}
擴容規則:
s + (s < (MIN_CAPACITY_INCREMENT / 2) ? MIN_CAPACITY_INCREMENT : s >> 1)
如果當前數組大小 s 小於6,則新數組大小爲 s+12;反之新數組大小爲1.5倍的s。
2、再看Vector
Java和Android中的Vector雖然實現有些差異,但默認數組大小都是10,擴容規則也是一樣:
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
capacityIncrement 爲構造器中傳入的一個值,如果傳了這個值,擴容就是當前數組大小+capacityIncrement ;
沒有傳入這個值得話,擴容後的數組就是當前數組的2倍。
可見,Vector是可以定製擴容基數的。
Vector是JDK1.0就有的API,當時是爲了多線程設計的,但是在JDK1.5後,新增了很多多線程安全的集合類,再加上Vector本身有很多缺點,所以不推薦使用Vector。