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 ...
随机推荐
- DDL_操作数据库_创建&查询和DDL_操作数据库_修改&删除&使用
DDL操作数据库.表 1.操作数据库:CRUD C(Create):创建 创建数据库: create database 数据库名称: 创建数据库判断不存在再创建 create database if ...
- Stream流中的常用方法
count package com.yang.Test.StreamStudy; import java.util.stream.Stream; /** * 统计荷属:count * 正如旧集合Col ...
- go更新腾讯云DNSPod的解析记录
纯粹练手用的,大家轻喷 获取SecretId,SecretKey 打开腾讯云,登录之后打开https://console.cloud.tencent.com/cam/capi,然后新建密钥记录生成的S ...
- 2507-AOP- springboot中使用-使用注解方式
Springboot中使用aop,与SSM中使用AOP,整体配置与编写方式都是类似的.但是Springboot简化了很多xml配置,切点的表达式可以直接进行javaconfig. 记录一些示例 spr ...
- Spark: Cluster Computing with Working Sets
本文是对spark作者早期论文<Spark: Cluster Computing with Working Sets>做的翻译(谷歌翻译),文章比较理论,阅读起来稍微有些吃力,但读完之后总 ...
- Javaweb-文件上传和邮件发送
1.文件上传 新建空项目 准备工作 在maven仓库里下载commons io 和 commons fileupload两个jar包 实用类介绍 文件上传注意事项 为保证服务器安全,上传文件应该放在外 ...
- 用JavaScript写一个进度条
var porpressBar = document.getElementById('progressBar') var info = document.getElementById('info') ...
- Java SE 9 多版本兼容 JAR 包示例
Java SE 9 多版本兼容 JAR 包示例 作者:Grey 原文地址:Java SE 9 多版本兼容 JAR 包示例 说明 Java 9 版本中增强了Jar 包多版本字节码文件格式支持,也就是说在 ...
- Vue3 组合式 API 中获取 DOM 节点的问题
模板引用 Vue 提供了许多指令让我们可以直接操作组件的模板.但是在某些情况下,我们仍然需要访问底层 DOM 元素.在模板中添加一个特殊的属性ref就可以得到该元素. 访问模板引用 <scrip ...
- 七分钟学会 HTML 网页制作
什么是HTML 点击打开视频讲解更加详细 Hyper Text Markup Language(超文本标记语言) 标签控制排版 体积小,方便传输 编写HTLML 推荐使用:VS Code <!D ...