1. 程式人生 > >ArrayList中set()和add()中你不知道的坑

ArrayList中set()和add()中你不知道的坑

一般使用List集合,估計都是使用這個ArrayList,一般呢也就是簡單遍歷資料和儲存資料。
很少使用到add(int index, E element)和set(int index, E element)兩個方法。
這兩個方法,乍一看,就是在指定的位置插入一條資料。
區別:
set()是更新,更新指定下標位置的值。
add()是新增,區別於一般的add(E e),這個就是有個位置的概念,特殊位置之後的資料,依次往後移動就是了。
然後,看下面程式碼。來看看陷阱。

就算是,你知道了上面的內容,也不能保證,你能安全的回答下面的程式碼執行結果。

public class ArrayListTest {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>(2);
        System.out.println("list大小為:" + list.size());
        list.add("12");
        System.out.println("list大小為:" + list.size());
        list.set(1,"sss");
        list.add(1,"放在下標為1的位置");
        list.add("22");
        System.out.println("list大小為:" + list.size());
        System.out.println(list.toString());
        list.add(1,"放在下標為1的位置");
        System.out.println("list大小為:" + list.size());
        System.out.println(list.toString());
    }
}

執行結果:
在這裡插入圖片描述
結果很出乎意料吧,下面我們看一下為啥會出現這種問題。
解釋:
1,List list = new ArrayList<>(2);
這個乍一看,還以為像陣列一樣,你初始化了個長度為2的陣列,然後你就可以隨意修改下標為0,1的內容。當然0,1是肯定不會下標越界的。
我當時也是這麼想的。然而不是的。
原始碼裡面的建構函式的註釋說明:這個真的是在底層新建了個長度為2的陣列Object[],但是他又不是我們經常看到的一般陣列。這個是空的。
當前list集合仍然是一個帶有初始容量的empty list。
2,list.size()
我上來也是想當然的以為,這個size()不就是上面的那個2嗎!但是我錯了。
原始碼中ArrayList的size屬性對應的註釋是:The size of the ArrayList (the number of elements it contains).
這個size是表示這個集合包含的元素的個數,而不是底層陣列的大小。
3,list.set(1,“sss”);
在知道了上面的2個坑之後,這個就好解釋了。程式碼是要設定下標為1的值,但是。在原始碼中有 rangeCheck(index);

    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

這個時候,index是1,但是size是1。
so,就異常啦。
4,list.add(1,“放在下標為1的位置”);
這個和上面相似,但還是有點不一樣,上面判斷是大於等於size,但是在這個add方法,卻是要大於才可以。
而且還有個專門的check方法for add,如下:rangeCheckForAdd(index);

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

那,這個在下標為1的位置,新增元素,判斷 1 > 1 不成立,那麼就可以順利添加了。這個就不異常啦。
但是,你要是在陣列宣告完,直接在下標為1的位置,這麼幹,就異常了。就不在繼續分析了。
5,還有個問題,就是你在一個位置一直add(index , element)。這個不僅僅是把index位置的資料給替換啦,而且把之前這個位置的資料給依次向後移動啦,這個跟map的結構不一樣,map是更新指定位置的資料,其他的資料不動,這個list竟然是把把資料平移了。