Java中ArrayList 自動擴容的內(nèi)存上的具體過程是怎樣的?
Java中ArrayList 自動擴容的內(nèi)存上的具體過程是怎樣的?為了答這個題,又去溫習了一遍ArrayList的源碼,姑且說下。。
JAVA中的很多基本數(shù)據(jù)結構都有動態(tài)擴容機制,比如hashMap,arraylist,之前說過了hashMap的擴容,現(xiàn)在說下arraylist的。。
arraylist的擴容發(fā)生在add()方法過程中,如下圖,先返回一個最新的size+1的數(shù)組,然后把加入的元素放入其中,如下圖:

上圖中的ensureCapacityInternal方法,主要是調(diào)用grow()方法,如下所示:

在grow方法中定義了一個新的數(shù)組容量newCapacity=oldCapacity +(oldCapacity >>1),>>符號代表左移一位,也就是除以2,換句話說新的容量擴容變?yōu)樵瓉淼?.5倍大??!然后將舊的所有元素通過使用Arrays.copyOf方法復制到新的數(shù)組中!

如下面的代碼所示:Arrays.copyOf方法內(nèi)部是調(diào)用的native方法System.arraycopy();這個方法會在內(nèi)存中創(chuàng)建一個新的數(shù)組,所以在擴容之后,返回的通常是一個新創(chuàng)建的數(shù)組,來替換原來的數(shù)組。

一般來說,list的自動擴容有兩個方面的問題:
①,性能:每次擴容都需要創(chuàng)建新的數(shù)組,并且復制原有數(shù)據(jù),如果一個arraylist存儲的數(shù)據(jù)過大,也就代表著擴容次數(shù)多,而且對內(nèi)存有很大的占用!
②,線程不安全:因為調(diào)用add方法中,有++操作,可能會在多線程環(huán)境下引起數(shù)組中元素為空,數(shù)據(jù)被覆蓋等問題,所以在多線程環(huán)境下,arrayList需要改為Collections.synchonizedList()來獲取一個安全的list實例!


