ArrayList扩容机制JDK1.8 (底层原理)

作者在学习过程中,遇到了ArrayList扩容的底层原理这一问题,查看JDK源码后有所理解故写此博客记录下来。

ArrayList简介

ArrayList 是 java 集合框架中比较常用的数据结构。继承自 AbstractList,实现了 List 接口。基于数组实现容量大小动态变化。同时还实现了 RandomAccess、Cloneable、Serializable 接口,所以ArrayList 是支持快速访问、复制、序列化的。

注:有关实现RandomAccess便支持快速访问,请查看另一篇文章实现RandomAccess接口支持快速访问原理

ArrayList初始化

创建ArrayList对象时,若未指定集合容量,集合默认容量为0

    //默认创建一个空集合
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = new Object[0];
    //ArrayList空参构造
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

当集合对象调用add方法存储数据时,进行容量初始化。底层实现如下:

    //ArrayList集合对象添加元素方法 
    public boolean add(E var1) {
        //扩容方法
        this.ensureCapacityInternal(this.size + 1);
        //存储元素
        this.elementData[this.size++] = var1;
        return true;
    }

    //添加元素时调用扩容方法
    private void ensureCapacityInternal(int var1) {
        //初始化状态时  默认容量变为10
        if (this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            var1 = Math.max(10, var1);
        }
        //非初始化状态时,判断集合是否需要扩容
        this.ensureExplicitCapacity(var1);
    }

结论1:
当集合对象第一次添加元素的时候,集合大小扩容为10(若使用addAll方法添加元素,则初始化大小为10添加集合长度较大值)

 

当集合初始化完毕后,再次添加元素时。调用其ensureExplicitCapacity方法

   private void ensureExplicitCapacity(int var1) {
        ++this.modCount;
        //如果最小需要空间比elementData的内存空间要大,扩容
        if (var1 - this.elementData.length > 0) {
            //核心扩容方法
            this.grow(var1);
        }

    }

    private void grow(int var1) {
        //获取原集合长度
        int var2 = this.elementData.length;
        //集合长度扩容1.5倍
        int var3 = var2 + (var2 >> 1);
        //如果扩容后仍小于添加集合的长度,新建集合长度为添加元素集合大小
        if (var3 - var1 < 0) {
            var3 = var1;
        }
        //若预设值大于默认的最大值检查是否溢出  
        if (var3 - 2147483639 > 0) {
            var3 = hugeCapacity(var1);
        }
        //调用Arrays.copyOf方法将elementData数组指向新的长度为扩容后长度的内存空间
        this.elementData = Arrays.copyOf(this.elementData, var3);
    }

结论2:
  集合初始化后,再次调用add方法,先将集合扩大1.5倍,如果仍然不够,新长度为传入集合大小。并调用Arrays.copyOf方法将elementData数组指向新的长度为扩容后长度的内存空间

总结

1.ArrayList创建对象时,若未指定集合大小初始化大小为0;若已指定大小,集合大小为指定的大小;

2.当第一次调用add方法时,集合长度变为10addAll内容之间较大值

3.之后再调用add方法,先将集合扩大1.5倍,如果仍然不够,新长度为传入集合大小;

你可能感兴趣的:(ArrayList扩容机制JDK1.8 (底层原理))