Java面试Day02-ArrayList底层结构和源码分析

先看一下集合的继承结构图

1.ArrayList中维护了一个Object类型的数组elementData。

2.当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。

3.如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容则直接扩容elementData为1.5倍。

ArrayList的特点包括:

  1. 动态大小:ArrayList的大小可以根据需要自动调整。它会根据添加或删除元素自动增加或减小容量,无需手动调整数组大小。
  2. 随机访问:ArrayList通过索引来访问元素,这意味着可以在O(1)的时间复杂度内访问特定位置的元素。因为ArrayList底层基于数组实现,所以可以直接通过下标访问元素。
  3. 可以存储任意类型的对象:ArrayList是泛型类,它可以存储任何类型的对象,包括基本数据类型的包装类和自定义对象。
  4. 有序集合:ArrayList中的元素按照添加的顺序排列,可以维持元素的插入顺序。
  5. 支持重复元素:ArrayList允许存储重复的元素,同一个元素可以多次出现在列表中。
  6. 方便的操作方法:ArrayList提供了一系列方法来操作和管理元素,包括添加、删除、修改、获取元素等。这些方法使得对元素的操作更加方便和灵活。
  7. 很少使用的位置为空:当删除元素时,ArrayList会将被删除元素的位置设置为空,但不会立即移动其他元素来填充空缺,而是在后续添加元素时才进行填充。

源码分析:

我们使用的无参构造器,所以应该像我们说的一样,初始elementData容量为0,如图所示:

首次添加数据时,调用add(E e)方法 e是传入的数据

跳入add(E e, Object[] elementData, int s)方法

在这里 s传入的是size值,初始为0,因此if条件成立,执行grow方法

进入此grow()方法,此grow方法返回一个Object数组

再次进入这个grow(int minCapacity)方法

首先把elementData数组的长度赋值给oldCapacity,然后进行判断。因为初始的elementData被这个常量赋值为0,并且oldCapacity等于0,所以if判断不成立。

通过max()方法,为elementData赋新值。

可以看到 DEFAULT_CAPACITY的值为10。

执行完这个方法后,返回一个长度为10的elementData数组

这样,ArrayList完成了它的第一次扩容。

接下来,我们来看当存入了十个数据后,如果要存入第十一个数据,ArraryList如何再次扩容。

首先还是一样,执行add(E e)方法,此时size已经等于10了。

然后执行add(E e, Object[] elementData, int s)方法,由于现在的数组长度等于了第一次扩容后的数组长度,即s = elementData.length ,所以判断成立,执行grow()方法。

还是和之前一样,再执行grow(int minCapacity)方法

此时oldCapacity = 10,已经大于0了,判断条件成立,执行if方法中的内容

这段代码设计数组扩容过程,具体解释如下:

ArraysSupport.newLength是一个用于计算新数组长度的方法,这个方法的目的是根据现有的数组容量、最小需要的容量以及偏好的容量增长值,计算出新数组的合适长度。

oldCapacity代表当前数组的容量大小。

minCapacity - oldCapacity的含义是最小需要容量与当前容量的差值,表示数组需要增长的最小空间大小。

oldCapacity >> 1是对当前容量进行右移一位操作,相当于将当前容量除以2,用作数组扩容时的偏好增长值。

newCapacity是根据上述参数计算得出的新数组容量。

这段代码执行后,把newCapacity赋给elementData,完成1.5倍扩容。

然后是返回elementData,可以看到执行grow()方法后,elementData的长度变成了15。

以上就是ArraryList数组扩容机制的源码分析。

前路漫漫亦灿灿。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值