java集合框架List之ArrayList(二)

来源:互联网 发布:淘宝一千多的硅胶娃娃 编辑:程序博客网 时间:2024/04/29 16:55

在上一篇文章,我们大概了解了ArrayList是个啥以及它的常用操作,那么对于某些操作的内部情况到底是怎么处理的,我们还没有实质性的了解,接下来我们一起来探讨探讨。

ArrayList的动态扩容

  • ArrayList初始化
    ArrayList提供三个构造器,一个是可以指定初始化容器的大小,一个是使用默认的容器大小,一个是使用另一个集合来作为自己的初始化元素,如下:
// 使用默认空间大小private static final int DEFAULT_CAPACITY = 10;// 默认无参构造器public ArrayList() {...}// 指定初始化空间的大小public ArrayList(int initialCapacity) {..}// 使用其它的集合来作为自己初始化的元素public ArrayList(Collection<? extends E> c) {...}
  • 下面我们来探讨一下使用无参构造器的第一次数据插入过程
// 使用无参构造器默认是一个长度为零的数组private static final Object[] EMPTY_ELEMENTDATA = {};// 数据入public boolean add(E e) {    // size初始=0  size+1=1    ensureCapacityInternal(size + 1);    elementData[size++] = e;    return true;}private void ensureCapacityInternal(int minCapacity) {    // 由于一开始啥都没有,将最小空间调整为10    if (elementData == EMPTY_ELEMENTDATA) {        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);    }    ensureExplicitCapacity(minCapacity);}private void ensureExplicitCapacity(int minCapacity) {    modCount++;    // elementData.length=0  10-0>0 进行第一次扩容    if (minCapacity - elementData.length > 0)        grow(minCapacity);// 扩容}// 扩容详情private void grow(int minCapacity) {    int oldCapacity = elementData.length;    // 此处决定了ArrayList每次扩容的大小 oldCapacity >> 1 每次扩容50% ,由于一开始的空间是0,所以这里的空间会变成10    int newCapacity = oldCapacity + (oldCapacity >> 1);    if (newCapacity - minCapacity < 0)        newCapacity = minCapacity;    if (newCapacity - MAX_ARRAY_SIZE > 0)        newCapacity = hugeCapacity(minCapacity);    // 将数据拷贝到新长度的数组中    elementData = Arrays.copyOf(elementData, newCapacity);}

综上所述,对于ArrayList的使用,尤其是频繁使用来讲,根据我们的业务场景我们是能大致判断出来一个ArrayList内所需空间的大小的,这个时候我们应该直接初始化指定大小空间的ArrayList出来,避免ArrayList进行扩容所带的一些性能问题,从而达到优化程序性能的效果。

在这里在着重重申一下 ##(oldCapacity >> 1)## 决定了ArrayList每一次扩容都会使容量增加50%, ArrayList的频繁扩容会带来性能问题,使用时指定初始化空间大小有利于性能提升

关于MAX_ARRAY_SIZE

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

我们能在代码内看到MAX_ARRAY_SIZE是在Integer值上限上面减了一个8的,为啥要减8呢?我们看一下它的注释

/*** The maximum size of array to allocate.* Some VMs reserve some header words in an array.* Attempts to allocate larger arrays may result in* OutOfMemoryError: Requested array size exceeds VM limit*/

由于有的VM对于数组的实现可能会在Array内带一些头部信息而导致分配空间值超出而造成OOM,所以将空间缩小了一下~_~

0 0