ArrayList底层原理

ArrayList底层原理

ArrayList在工作中经常用到,今天来看一下ArrayList的底层是如何实现的?在这之前,先抛出几个问题。

1.ArrayList底层实现的数据结构是什么?

2.ArrayList的初始化容量是多少,底层的扩容机制是什么?

3.ArrayList是在什么时候初始化容量的?

4.ArrayList是如何实现添加元素操作的?

//实现了List接口,实现了List的常用方法,如add(E e)
//实现了RandomAccess接口,这是个标记接口,接口中没有任何方法,作用只是标记ArrayList可以支持快速随机访问
//实现了Cloneable接口,表示ArrayList实例调用clone()可以克隆一个和自己一样的实例(这里是浅拷贝)。
//实现了Serializable接口,表示可以序列化和反序列化,可以在网络中传输。
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;
    //默认容量是10
    private static final int DEFAULT_CAPACITY = 10;
    private static final Object[] EMPTY_ELEMENTDATA = {};
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    //底层使用Object数组实现的,所有可以存任何类型
    transient Object[] elementData;  
    private int size;
    //代码太多,省略......
}

下面代码是ArrayList添加一个元素的底层实现

这两行代码,底层帮我们做了什么?debug进去看看

ArrayList arrayList = new ArrayList<>();
arrayList.add(new String("I am xiao qiang"));

首先是类加载器,他的作用是将class文件加载到jvm虚拟机中
请添加图片描述
接着进入到了ArrayList的构造方法中,可以看到构造方法给elementData赋了一个空值,说明此时仅仅创建一个ArrayList对象,除此之外没有做任何事情。

这也说明,我们只是创建了ArrayList对象,它并没有初始化容量。
请添加图片描述
接下来dubug进入到了add()方法中
请添加图片描述
进入到String的构造方法中,创建出String字符串对象,并赋值“I am xiao qiang”
请添加图片描述
继续debug,终于执行了ArrayList的add()方法,ensureCapacityInternal是判断是否要扩容的方法,进入该方法
请添加图片描述
可以看到底层是调用了一个计算容量的方法calculateCapacity,然后将默认容量10返回了,这说明ArrayList容量的初始化是在添加元素add()方法后进行的
请添加图片描述
接着继续执行add()方法,elementData[0]被赋值成"I am xiao qiang"
请添加图片描述
到此,两行代码终于结束了。
请添加图片描述
下面我们看一下ArrayList扩容机制的代码。

如果minCapacity的值大于add数据之前的大小,就调用grow方法,进行扩容,否则什么也不做。

下面是具体看出来扩容机制的大小增长规则了:

private void grow(int minCapacity) {  
       // overflow-conscious code  
       int oldCapacity = elementData.length;  
    //oldCapacity >> 1就是1/2 oldCapacity
       int newCapacity = oldCapacity + (oldCapacity >> 1);  
       if (newCapacity - minCapacity < 0)  
           newCapacity = minCapacity;  
       if (newCapacity - MAX_ARRAY_SIZE > 0)  
           newCapacity = hugeCapacity(minCapacity);  
       // minCapacity is usually close to size, so this is a win:  
       elementData = Arrays.copyOf(elementData, newCapacity);  
   }  

注意:这里传过来的minCapcatiy的值是size+1,能够实现grow方法调用就肯定是(size+1)>elementData.length的情况,所以size就是初始最大容量或上一次扩容后达到的最大容量,所以才会进行扩容。newCapacity=oldCapacity+(oldCapacity>>1),这里就是扩容大小确定的地方,相当于新的最大容量是 size+1+size/2 相当于原来的1.5倍然后加1
最新大厂IT课程:点击获取

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值