Java和Android中ArrayList與Vector的擴容比較

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。

發佈了32 篇原創文章 · 獲贊 8 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章