20220929-ArrayList扩容机制源码分析
示例代码
public class ArrayListSource {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList(); //跳转至第一步
for (int i = 0; i < 10; i++) {
arrayList.add(i); //需要进行第一次扩容,跳转至第二步
}
for (int i = 11; i <= 15; i++) {
arrayList.add(i); //需要进行第二次扩容
}
arrayList.add(100); //需要进行第三次扩容
arrayList.add(200);
arrayList.add(300);
}
}
代码分析
第一步:
当使用new ArrayList()创建集合时,会调用ArrayList类的无参构造器,在集合内部存在一个空的elementData数组,代码如下
private static final int DEFAULT_CAPACITY = 10; //默认容量
...
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //默认空数组
...
transient Object[] elementData; //存放Object对象的数组
...
private int size; //集合中所包含的元素,默认为0
...
protected transient int modCount = 0;
...
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //MAX_ARRAY_SIZE = 2147483639
...
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //elementData初始化为{}数组,其中size=0
}
第二步:
程序进入for循环,从i=0开始,执行arrayList.add(i)方法,进入ArrayList类中
public boolean add(E e) { //此时:e=1
ensureCapacityInternal(size + 1); //跳转至第三步
elementData[size++] = e;
return true;
}
第三步:
执行ensureCapacityInternal(size + 1),其中size=0
private void ensureCapacityInternal(int minCapacity) { //此时minCapacity=size+1=1,即给集合中添加1个元素,需要的最小容量是1
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); //跳转至第四步
}
第四步:
先执行ensureExplicitCapacity()中的嵌套函数calculateCapacity(elementData, minCapacity)
// elementData = {}
// minCapacity = 1
// DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}
// DEFAULT_CAPACITY = 10
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //此if语句成立
return Math.max(DEFAULT_CAPACITY, minCapacity); //返回值为10,退出函数,跳转至第五步,
}
return minCapacity;
}
第五步:
执行ensureExplicitCapacity()函数
// minCapacity = 10
// modCount默认为0,然后自加1
// elementData.length = 0
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0) //此时if语句成立
grow(minCapacity); //跳转至第六步
}
第六步:
执行grow(minCapacity)
// minCapacity = 10
// MAX_ARRAY_SIZE = 2147483639
private void grow(int minCapacity) {
int oldCapacity = elementData.length; //oldCapacity=0
int newCapacity = oldCapacity + (oldCapacity >> 1); //newCapacity=0+0/2=0
if (newCapacity - minCapacity < 0) //此if语句成立
newCapacity = minCapacity; //newCapacity = 10
if (newCapacity - MAX_ARRAY_SIZE > 0) //此if语句不成立
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
//此语句执行后,elementData = {null,null,null,null,null,null,null,null,null,null}
}
第七步:
当程序执行完第六步之后,根据方法调用步骤依次返回,直至第二步的第2条程序语句
public boolean add(E e) {//此时:e=1
ensureCapacityInternal(size + 1);
//通过以上方法,确保集合中可以存放e对象
elementData[size++] = e;//此时size=0,之后自加1;e=1
//执行之后 elementData = {1,null,null,null,null,null,null,null,null,null}
return true;
}
第八步:
在for循环中,不断执行 arrayList.add(i)方法,直到for循环结束,以上步骤介绍了ArrayList第一次默认初始化之后存放元素的步骤和扩容机制,当集合中存放的对象达到容量10时,集合需要再次进行扩容。而接下来的每次扩容的容量=原来容量*1.5,即 0 --> 10 --> 15 --> 22 --> 33...
20220929-ArrayList扩容机制源码分析的更多相关文章
- JAVA ArrayList集合底层源码分析
目录 ArrayList集合 一.ArrayList的注意事项 二. ArrayList 的底层操作机制源码分析(重点,难点.) 1.JDK8.0 2.JDK11.0 ArrayList集合 一.Ar ...
- Android事件分发机制源码分析
Android事件分发机制源码分析 Android事件分发机制源码分析 Part1事件来源以及传递顺序 Activity分发事件源码 PhoneWindow分发事件源码 小结 Part2ViewGro ...
- ArrayList详解-源码分析
ArrayList详解-源码分析 1. 概述 在平时的开发中,用到最多的集合应该就是ArrayList了,本篇文章将结合源代码来学习ArrayList. ArrayList是基于数组实现的集合列表 支 ...
- Springboot学习04-默认错误页面加载机制源码分析
Springboot学习04-默认错误页面加载机制源码分析 前沿 希望通过本文的学习,对错误页面的加载机制有这更神的理解 正文 1-Springboot错误页面展示 2-Springboot默认错误处 ...
- ApplicationEvent事件机制源码分析
<spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...
- 2.8.2 并发下的ArrayList,以及源码分析
package 第二章.并发下的ArrayList; import java.util.ArrayList;import java.util.List; /** * Created by zzq on ...
- Android查缺补漏(View篇)--事件分发机制源码分析
在上一篇博文中分析了事件分发的流程及规则,本篇会从源码的角度更进一步理解事件分发机制的原理,如果对事件分发规则还不太清楚的童鞋,建议先看一下上一篇博文 <Android查缺补漏(View篇)-- ...
- ArrayList 和 LinkedList 源码分析
List 表示的就是线性表,是具有相同特性的数据元素的有限序列.它主要有两种存储结构,顺序存储和链式存储,分别对应着 ArrayList 和 LinkedList 的实现,接下来以 jdk7 代码为例 ...
- List中的ArrayList和LinkedList源码分析
List是在面试中经常会问的一点,在我们面试中知道的仅仅是List是单列集合Collection下的一个实现类, List的实现接口又有几个,一个是ArrayList,还有一个是LinkedLis ...
随机推荐
- vivado没用上的寄存器变量
vivado中定义了但没用上的寄存器变量,在综合时会被移除,即没有综合出来.(如下cnt,虽然在y的过程块中用了cnt作为判断条件,但实际上cnt用了跟没用效果一样,所以综合时cnt_reg就被放弃了 ...
- 86开关、家电、台扇等6键6路6感应通道高抗干扰触摸IC-VK3606D,稳定性好,抗干扰能力强
概述: VK3606D SOP16具有6个触摸按键,可用来检测外部触摸按键上人手的触摸动作.该芯片具有较高的集成度,仅需极少的外部组件便可实现触摸按键的检测.提供了6路1对1直接输出低电平有效.最长输 ...
- RabbitMQ细说之开篇
前言 关于消息中间件的应用场景,小伙伴们应该都耳熟能详了吧,比如经常提到的削峰填谷.分布式事务.异步业务处理.大数据分析等等,分布式消息队列成为其中比较关键的桥梁,也就意味着小伙伴们得掌握相关技能:当 ...
- python subprocess相关操作
python subprocess常用操作 1.subprocess模块的常用函数 函数 描述 subprocess.run() Python 3.5中新增的函数.执行指定的命令,等待命令执行完成后返 ...
- 快速体验Spring Boot了解使用、运行和打包 | SpringBoot 2.7.2学习系列
SpringBoot 2.7.2 学习系列,本节内容快速体验Spring Boot,带大家了解它的基本使用.运行和打包. Spring Boot 基于 Spring 框架,底层离不开 IoC.AoP ...
- JavaWeb--Cookie与Session
前言 Java Web 其实就是一个技术的总和,把Web看成一个容器而已主要使用JavaEE技术来实现.在加上各种中间件. 整个javaWeb阶段的内容通过实际的案例贯穿学习, 所涉及到的技术知识点会 ...
- 从零开始Blazor Server(10)--编辑角色
例图 目前的样式是这样的: 其中角色在一个table里,然后可以增删改查,并且可以给指定的用户分配权限. 创建文件 首先我们在Pages/Admin目录下新建一个Role.razor.因为我们的Adm ...
- 一个注解搞定SpringBoot接口定制属性加解密
前言 上个月公司另一个团队做的新项目上线后大体上运行稳定,但包括研发负责人在内的两个人在项目上线后立马就跳槽了,然后又交接给了我这个「垃圾回收人员」. 本周甲方另一个厂家的监控平台扫描到我们这个项目某 ...
- 基于.NetCore开发博客项目 StarBlog - (17) 自动下载文章里的外部图片
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- net::ERR_BLOCKED_BY_CLIENT 错误导致页面加载不出来
AdBlock 禁止广告的插件屏蔽你的网络请求,屏蔽了一些重要的文件,导致页面加载不出来. 解决方案: 1.修改资源文件的名称,把ad替换成其他字符: 2.关闭广告拦截器: 3.广告拦截器设置白名单.