一、ArrayList的扩容原理及过程
当我们创建了一个ArrayList对象并调用它的add方法

    List list=new ArrayList();list.add("嘿嘿");list.add("嘿嘿");list.add("嘿嘿");list.add("嘿嘿");list.add("嘿嘿");list.add("嘿嘿");list.add("嘿嘿");list.add("嘿嘿");list.add("嘿嘿");list.add("嘿嘿");list.add("嘿嘿");//一共添加11个元素,用来测试集合长度如何扩容

按住ctrl键后鼠标点击ArrayList类进入源码,
(1)可以发现它的底层其实是一个Object类型的数组变量elementData,(在此可以大胆猜想我们添加的元素可能就是存入这个数组中)

     transient Object[] elementData;

(2)在new ArrayList()对象时,毫无疑问执行的是ArrayList的无参构造方法,具体如下
可以看到将一个名为DEFAULTCAPACITY_EMPTY_ELEMENTDATA的空数组赋值给了elementData变量,
到此无参构造方法执行结束,也就是说:new一个无参ArrayList,底层创建的仅仅是一个长度为0的空数组。

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}

(3)开始第一个元素,执行add方法 ,代码如下
首先size变量目前还未赋值,因此大小为系统给的初始值0,
size其实代表的就是我们实际放入集合中的元素个数(而非elementData.length)。
接下来执行 ensureCapacityInternal(size + 1)这个方法,就是去检测以下容器(elelmentData数组)长度是否够用,
将size+1的值作为是否触发扩容的标准,这个值满足内在的设计条件,则扩容,不满足就不扩容,表示elementData数组容量还凑合,暂时不加长了。具体代码在下面,将在注释中解释这个过程。

调用add方法添加第一个元素执行的代码

     private int size;public boolean add(E e) {ensureCapacityInternal(size + 1);  // 将size+1的值作为判断接下来要不要扩容的标准,具体代码就在下一个方法,elementData[size++] = e;//扩容后的长度为10的数组elementData,因为是Object类型,因此里面是系统给的初始值全部都为null,//并将下标为size:0处的null改为元素e:"嘿嘿",然后size+1,即有效元素为1return true;//添加完毕,返回true}   //private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//检测size+1的长度是否需要扩容private static final int DEFAULT_CAPACITY = 10;private void ensureCapacityInternal(int minCapacity) {//此时传入的minCapacity=size+1=0+1=1if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//此时的elementData={},因此满足这个条件,minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//DEFAULT_CAPACITY = 10,所以10和1最大值为10赋值给minCapacity变量}ensureExplicitCapacity(minCapacity);//minCapacity=10;}protected transient int modCount = 0;//将10这个长度再拿过来检测private void ensureExplicitCapacity(int minCapacity) {modCount++;if (minCapacity - elementData.length > 0)//此时elementData依然是一个空数组,因此10-0>0  条件成立,grow(minCapacity); //开始执行核心扩容方法}private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;private void grow(int minCapacity) {//minCapacity=10int oldCapacity = elementData.length;//此时elementData依然是空数组,长度自然为0,因此oldCapacity=0int newCapacity = oldCapacity + (oldCapacity >> 1);```**>>1 这个表示是二进制右移一位,0右移一位依然是0,因此newCapacity=0+0=0,后面当添加到11个元素时,也会在此扩容,扩容后的长度就是这样子算的,  10+10>>1   右移1位相当于乘以0.5 ,因此newCapacity=10+10*0.5=15  ,也就是说,扩容倍数为1.5倍**```java      if (newCapacity - minCapacity < 0)//minCapacity:传入方法参数值10,   0-10=-10<0 为true,if成立newCapacity = minCapacity;   //将10赋值给新的数组长度   newCapacity=10if (newCapacity - MAX_ARRAY_SIZE > 0)// MAX_ARRAY_SIZE =int的4个字节一共32位bit的最大值大概21亿多减去8的值,显然不成立newCapacity = hugeCapacity(minCapacity);elementData = Arrays.copyOf(elementData, newCapacity);//通过Arrays工具类将老数组内容复制到一个新的数组,并指定此数组的长度为newCapacity:10   ,因此grow完成了扩容,返回的是长度为10的数组,里面存了系统给的默认值10个null。 }

总结:对于ArrayList ,new无参对象时,底层是一个空数组,当添加第一个元素时,会进行扩容,将底层数组长度扩为10,
其中扩容触发的条件是:存元素时,即先让size+1的值判断是否大于底层elementData.length的长度,如果大于,则先扩容再添加,
扩容的倍数为1.5倍。

4、ArrayList的详细扩容过程相关推荐

  1. linux双系统 魔术师,双系统Ubuntu分区扩容过程记录

    本人电脑上安装了Win10 + Ubuntu 12.04双系统.前段时间因为在Ubuntu上做项目要安装一个比较大的软件,导致Ubuntu根分区的空间不够了.于是,从硬盘又分出来一部分空间,分给Ubu ...

  2. (转载)连连看游戏外挂详细制作过程

    标 题: [原创]新人入手第一个游戏外挂,附上详细制作过程 作 者: caigui 时 间: 2013-01-09,00:56:16 链 接: http://bbs.pediy.com/showthr ...

  3. 详解java集合之ArrayList——底层实现是一个Object数组。分析ArrayList的自动扩容,原来不一定是1.5倍

    ArrayList的底层实现--非private权限的Object数组 ArrayList的类结构图 1. ArrayList的创建 1.1 参数为空的构造方法--ArrayList内部的Object ...

  4. 单片机驱动DM9000网卡芯片(详细调试过程)【下】

    http://hi.baidu.com/mcu8031/blog/item/c95903138671c625dc540171.html 单片机驱动DM9000网卡芯片(详细调试过程)[下] 4.验证初 ...

  5. spark集群详细搭建过程及遇到的问题解决(四)

    在spark集群详细搭建过程及遇到的问题解决(三)中,我们将讲述了hadoop的安装过程,在本文中将主要讲述spark的安装配置过程. spark@master:~/spark$ cd hadoop ...

  6. d9900 修改ip 思科dcm_思科设备SSH登陆详细配置过程

    思科设备SSH登陆详细配置过程 我们用GNS3进行拓扑搭建. 实验拓扑图如下: 进行完基本配置之后开始配置SSH服务器(R2) 1.首先验证设备是否支持SSH R2#show ip ssh 能够识别这 ...

  7. zabbix3.0.2 使用percona mysql插件来监控mysql5.7的详细实现过程

    zabbix3.0.2 使用percona mysql插件来监控mysql5.7的详细实现过程 --前言 上次用了zabbix自带的mysql插件来监控mysql数据库,但是太过简陋了,对于我们dba ...

  8. 主动模式下FTP的详细工作过程

    文中有不对或者有不清楚的地方,请大家告诉我,谢谢!   主动模式下FTP的详细工作过程   PORT FTP是常用的FTP工作方式,当客户端的连接请求到来时,FTP服务器会利用默认的21端口与客户端建 ...

  9. 12、图解横向扩容过程,如何超出扩容极限,以及如何提升容错性

    1.图解横向扩容过程,如何超出扩容极限,以及如何提升容错性 (1)primary&replica自动负载均衡,6个shard,3 primary,3 replica (2)每个node有更少的 ...

最新文章

  1. flume bucketpath的bug一例
  2. MSSQL 漏洞利用与提权
  3. iView 实现可编辑表格
  4. SAP Backgroud job
  5. 理清ThreadLocal、ThreadLocalMap、Thread之间的关系
  6. 用 DomIt! XML 处理工作
  7. java input属性_如何在h:inputText中指定命令属性?
  8. JQuery-让Ajax变的更简单
  9. TF实战:(Mask R-CNN原理介绍与代码实现)-Chapter-8
  10. centos6安装mysql权限被拒绝_CentOS6.6安装mysql出现的问题
  11. javascript学习系列(12):数组中的join方法
  12. mysql抽屉图标_React Native自定义组件实现抽屉菜单控件效果
  13. open() api
  14. java抛出异常thorw和throws的用法
  15. 小米手机hbuilder开发者模式
  16. 数据分析岗位求职经验分享
  17. 解决pycharm下载第三方库失败
  18. 苹果换原装电池_航空港区正规苹果换原装屏幕价目表
  19. 【FCN】Fully Convolutional Networks for Semantic Segmentation学习
  20. 注意力缺陷/多动障碍和睡眠障碍之间有什么联系?基于大规模队列多模态研究

热门文章

  1. 介绍Python/Django的在线好书推荐
  2. 职场回头草 是糖是毒药
  3. 2021最新免费申请微软A1plus账号,免费获得office365
  4. 计算机硬件相关文献,计算机硬件维护外文外文 计算机硬件维护专著类参考文献哪里找...
  5. mysql bak 还原数据库文件格式_Navicat操作SQL server 2008R2文件.bak文件还原
  6. HBuilderX的下载和安装--详细
  7. java接收文件流并操作文件流
  8. 当电摇家族进入C++(二)
  9. 桌面时钟(JS版本)-electron
  10. xcode7 如何真机测试