天天看點

ArrayList.add(index, element)失敗,都是size的誤解

在使用ArrayList時遇到一個很愚蠢的問題,想在大小為10的ArrayList的第5個位置插入10,結果抛異常。代碼示例如下

ArrayList<Integer> arr=new ArrayList<Integer>(10);
arr.add(5, 10);
           

異常為

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 5, Size: 0
	at java.util.ArrayList.rangeCheckForAdd(ArrayList.java:643)
	at java.util.ArrayList.add(ArrayList.java:455)
           

很是郁悶,明明初始化了大小為10的空間,跑出的異常卻告訴我size為0。好吧,隻能直接點進去看源代碼了。版本1.7

public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }
           

add方法,從異常看,是rangeCheckForAdd(index);這行,點進去,為rangeCheckForAdd(int index)這個函數

private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
           

最終抛出去的異常内容來源為:

private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }
           

這就是開始那個異常 Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 5, Size: 0   

接下來隻能看Size為啥為0了,源代碼:

/**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;
           

貌似真相大白了,size隻是此ArrayList所包含的元素個數,不是它的容量大小。

那麼怎麼辦呢?看ArrayList的帶參數構造函數

public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }
           

是以在構造函數裡,根本就沒有對size進行操作指派,是以size == 0。但是在add時他又強制檢查。是以隻好都add一遍,讓size遞增,然後去從新set這個值:

for (int i = 0; i < 10; i++) {
  arr.add(0);
}
arr.set(5, 10);
           

但是有沒有感覺這種方法很愚蠢呢?

還是本來ArrayList就不适合做這種直接插入的操作吧!還沒有直接用數組操作友善。