Java中ArrayList 自动扩容的内存上的具体过程是怎样的?
Java中ArrayList 自动扩容的内存上的具体过程是怎样的?为了答这个题,又去温习了一遍ArrayList的源码,姑且说下。。
JAVA中的很多基本数据结构都有动态扩容机制,比如hashMap,arraylist,之前说过了hashMap的扩容,现在说下arraylist的。。
arraylist的扩容发生在add()方法过程中,如下图,先返回一个最新的size+1的数组,然后把加入的元素放入其中,如下图:
上图中的ensureCapacityInternal方法,主要是调用grow()方法,如下所示:
在grow方法中定义了一个新的数组容量newCapacity=oldCapacity +(oldCapacity >>1),>>符号代表左移一位,也就是除以2,换句话说新的容量扩容变为原来的1.5倍大小!然后将旧的所有元素通过使用Arrays.copyOf方法复制到新的数组中!
如下面的代码所示:Arrays.copyOf方法内部是调用的native方法System.arraycopy();这个方法会在内存中创建一个新的数组,所以在扩容之后,返回的通常是一个新创建的数组,来替换原来的数组。
一般来说,list的自动扩容有两个方面的问题:
①,性能:每次扩容都需要创建新的数组,并且复制原有数据,如果一个arraylist存储的数据过大,也就代表着扩容次数多,而且对内存有很大的占用!
②,线程不安全:因为调用add方法中,有++操作,可能会在多线程环境下引起数组中元素为空,数据被覆盖等问题,所以在多线程环境下,arrayList需要改为Collections.synchonizedList()来获取一个安全的list实例!
arrayList和hashMap可以说是JAVA开发人员遇到的最多的两个数据结构,但是往往有很多容易忽略的小坑,所以基础学习很重要。