ArrayList无参构造添加元素源码解读
一、ArrayList无参构造add方法源码阅读
@Test//无参构造源码阅读
public void testArrayListNoConstructorAdd(){ArrayList<Integer> arrayList = new ArrayList<>();ArrayList<Integer> list = new ArrayList<>();arrayList.add(1);arrayList.add(12);arrayList.add(13);
}
就用这个为测试吧。
对于arrayList.add(1)
debug进去:
看到进来了这里:
1、来到Integer类方法内部
public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);
}
对于IntegerCache.cache[i + (-IntegerCache.low)];
这里应该是将cache索引为i - IntegerCache.low的元素返回,对于cache这个数组存储的个数是2x128 = 28
也就是可以存储[-128,127]这些元素。
不信可以借助工具查看:
发现确实是这样。
2、来到ArrayList的add方法:
public boolean add(E e) {ensureCapacityInternal(size + 1); // Increments modCount!!elementData[size++] = e;return true;
}
size是什么?查看一下:
/*** The size of the ArrayList (the number of elements it contains).** @serial*/
private int size;
确实是大小,实锤了!!!
3、来到ensureCapacityInternal
private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));//elementData是Object[0]@1098,不知道是什么,minCapacity是1
}
4、来到calculateCapacity:
private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//defaultcapacity_empty_elementdata这里是true的。return Math.max(DEFAULT_CAPACITY, minCapacity);//DEFAULT_CAPACITY=10/**DEFAULT_CAPACITY: Default initial capacity.private static final int DEFAULT_CAPACITY = 10;*/}return minCapacity;
}
返回到:
ensureExplicitCapacity - > "Explicit是明确的意思"
来到:
private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0)grow(minCapacity);
}
minCapacity >elementData.length成立:
private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;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);
}
来到Arrays.copyof:
这里的original是一个对象吧
看到上一步是:
//类成员:transient Object[] elementData;
也就是elementData这个玩意,忍了很久了,之前一度怀疑这个是不是存储节点的数据,看看它的介绍发现果然是:
* The array buffer into which the elements of the ArrayList are stored.* The capacity of the ArrayList is the length of this array buffer. Any* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA* will be expanded to DEFAULT_CAPACITY when the first element is added.翻译下:* 存储 ArrayList 元素的数组缓冲区。* 数组列表的容量是此数组缓冲区的长度。任何* 空的数组列表与元素数据 == DEFAULTCAPACITY_EMPTY_ELEMENTDATA* 将在添加第一个元素时扩展到 DEFAULT_CAPACITY。
那么就继续copyof这个方法:
public static <T> T[] copyOf(T[] original, int newLength) {return (T[]) copyOf(original, newLength, original.getClass());
}
首先,分析一下这个类,返回的是一个T泛型类,那么也就是和elementData同一个类型的对象。
来到:
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {@SuppressWarnings("unchecked")T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;
}
应该是走(Object)newType == (Object)Object[].class
是true,于是走这边(T[]) new Object[newLength]
了,然后再来到:
System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));
这里很明显是将original的这里的内容拷贝到新的对象copy这个对象里了
,然后再返回新对象给:
public static <T> T[] copyOf(T[] original, int newLength) {
再回到:
private void grow(int minCapacity) {
返回copy给elementData.
再回到ArrayList的这个方法把里面的grow方法执行完再结束:
private void ensureExplicitCapacity(int minCapacity) {
结束。
再回到:
private void ensureCapacityInternal(int minCapacity) {
再回到add方法将最后2行执行完就结束:
public boolean add(E e) {ensureCapacityInternal(size + 1); // Increments modCount!!elementData[size++] = e;return true;
}
二、回顾:
第一步先去确认下容器大小怎么样。
如果是第一次add,就给10个容量。人哈就去扩容也就是grow方法。
这里的grow是怎么扩容呢?
看看源码:
private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1);if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)//如果比MAX_ARRAY_SIZE这个都大,那么就去newCapacity = hugeCapacity(minCapacity);//获取更大的容量// minCapacity is usually close to size, so this is a win:elementData = Arrays.copyOf(elementData, newCapacity);
}
这里就是先按照增加原来的一半容量吧。从int newCapacity = oldCapacity + (oldCapacity >> 1)
可以看出。>>
这个符号就是有符号右移嘛,也就是除以2。
总结一下:
对于无参构造创建的ArrayList,一开始容器大小也就是size = 0,当要添加元素时,便是第一次添加元素,会扩容10个大小。后面继续添加元素时每次都会和之前的容量大小比较一下,刚好不够了再扩容,扩大50%。
先做数据的迁移,再做数据的添加。
如果是第二次扩容1,那么就是添加第11个元素时,先去grow一下,新创建数组大小为15的copy(也就是扩容),然后迁移数据。然后再将copy返回给elementData,再进行add,将元素添加到已经扩容了的elementData的末尾,可以使用这个来查看一下:
@Test//无参构造源码阅读
public void testArrayListNoConstructorAdd(){ArrayList<Integer> arrayList = new ArrayList<>();ArrayList<Integer> list = new ArrayList<>();for (int i = 0; i <20; i++) {arrayList.add(i);}
}
过程和本文讲解的是一样的。
end
相关文章:

ArrayList无参构造添加元素源码解读
一、ArrayList无参构造add方法源码阅读 Test//无参构造源码阅读 public void testArrayListNoConstructorAdd(){ArrayList<Integer> arrayList new ArrayList<>();ArrayList<Integer> list new ArrayList<>();arrayList.add(1);arrayList.add(12);a…...

手写简易 Spring(二)
文章目录手写简易 Spring(二)1. 扩展 BeanFactory 接口2. 实现资源加载器,从 Spring.xml 解析和注册 Bean 对象1. 核心实现类 XmlBeanDefinitionReader3. 实现应用上下文,自动识别、资源加载、扩展机制1. 应用上下文2. 核心实现类…...
排列问题DFS入门
1、题目描述(全排列) 输入一个正整数n,输出1~n的全排列。 输入格式 一个正整数n。 输出格式 所有1~n的全排列,每个排列占一行。 样例输入 3 样例输出 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 算法思路 题目要求输出n的全…...
【每日一题Day159】LC1638统计只差一个字符的子串数目 | 枚举
统计只差一个字符的子串数目【LC1638】 给你两个字符串 s 和 t ,请你找出 s 中的非空子串的数目,这些子串满足替换 一个不同字符 以后,是 t 串的子串。换言之,请你找到 s 和 t 串中 恰好 只有一个字符不同的子字符串对的数目。 比…...

【07 Metadata and VendorTag】
1. Metadata结构及分类 一个 metadata 通过tag,value及 type 来描述。不同的 metadata 分成三类 controls,dynamic 及 static 2. MTK Metadata IMetadata Mtk metadata containerIMetadataConverter Provide mutual conversion for Android camera_metadata and MTK Imetada…...

Golang中Model的使用
导语我们都知道在Golang中我们一般都是设置GOPATH目录,这个目录主要存放我们的第三方包,这个方式一直不是很方便,今天给大家介绍Go 1.11版本中推出的GoModul使用方法,学过java的同学,可能对maven包有所了解,…...

交友项目【基础环境搭建】
目录 1:交友项目架构介绍 1.1:前后端分离的概述 1.2:YAPI介绍(虚拟机中已经配好) 基本信息 使用 安装跨域拓展(浏览器上安装跨域处理插件) 2:虚拟机工具项目搭建 2.1࿱…...

入职时,公司要求自己带电脑,每月给100元补贴,如果不接受就不能入职!
为了节约成本,公司能做出什么事?一位网友遇到了这样的事:入职时,公司要求自己带电脑,每个月给100元补贴,如果不接受就得放弃入职,这样的公司有没有坑?有人问:连基本的公司…...

20道经典Redis面试题
20道经典Redis面试题 前言 整理了20道经典Redis面试题,希望对大家有帮助。 1. 什么是Redis?它主要用来什么的? Redis,英文全称是Remote Dictionary Server(远程字典服务),是一个开源的使用A…...

十分钟带你看懂接口测试,2023最全超大型接口测试攻略
一、什么是接口测试? 所谓接口,是指同一个系统中模块与模块间的数据传递接口、前后端交互、跨系统跨平台跨数据库的对接。而接口测试,则是通过接口的不同情况下的输入,去对比输出,看看是否满足接口规范所规定的功能、…...

【设计模式】创建型-单例模式
文章目录一、单例模式二、单例模式的八种实现方式2.1、饿汉式(静态常量)2.2、饿汉式(静态代码块)2.3、懒汉式(线程不安全)2.4、懒汉式(线程安全,同步方法)2.5、双重检查2…...

Python 练习 六
1、(最大数的出现)编写程序读取整数,找出它们中的最大值,然后计算它的出现次数。假设输入以数字0结束。假设你输入的是“352555 0";程序找出的最大数是5,而5的出现次数是4。(提示:维护两个变量max和 count。变量max存储的是当前最大数,而…...
「SQL面试题库」 No_22 员工奖金
🍅 1、专栏介绍 「SQL面试题库」是由 不是西红柿 发起,全员免费参与的SQL学习活动。我每天发布1道SQL面试真题,从简单到困难,涵盖所有SQL知识点,我敢保证只要做完这100道题,不仅能轻松搞定面试࿰…...

瞒不住了,Prefetch 就是一个大谎言
本文正在参加「金石计划」 Prefetch 是一个谎言 我们知道,现在的应用程序已经发展到可以拆分为多个 JavaScript包了,为了获得更好的用户体验,这些 bundle 包通常需要预获取,即 prefetch! 但是现在的prefetch 效果有多糟糕我想你…...

这个时候了,你还不会不知道JavaMail API吧
一、概述 1.1 简述 JavaMail API 顾名思义,提供给开发者处理电子邮件相关的编程接口,它是Sun发布的用来处理email的API,其提供独立于平台且与协议无关的框架来构建邮件和消息传递应用。JavaMail API 提供了一组抽象类,用于定义组…...
JavaScript var let区别
文章目录JavaScript var & let区别变量作用域变量提升变量重复声明全局对象属性for循环中的作用域JavaScript var & let区别 var和let都是用来声明变量的关键字。 变量作用域 var声明的变量作用域是函数作用域或全局作用域,而let声明的变量作用域是块级作…...
Thinkphp 6.0容器和依赖注入
本节课我们来学习一下依赖注入的用法,以及容器的用法。 一.依赖注入 1. 手册对依赖注入比较严谨的说明,具体如下: 依赖注入其实本质上是指对类的依赖通过构造器完成自动注入,例如在控制器架构方法和操作 方法中一旦对参…...
Type javax.servlet.http.HttpServletRequest not present
运行环境 Swagger 3.0.0、springboot 3.0.0 产生原因: Swagger 3.0.0不支持spring3.0.0 两个解决方案: 1.降低springboot版本为2.x 2.放弃Swagger,使用 springdoc-openapi-starter-webmvc-ui 第二种解决方案: <dependen…...
一键配置Ubuntu的OpenHarmony基础编译环境
一键配置Ubuntu的OpenHarmony基础编译环境 一、配置前说明 该更新源仅适用于Ubuntu以下系列 Ubuntu18.04 Ubuntu20.04 Ubuntu22.04 强烈推荐Ubuntu20.04,本人使用的一直都是Ubuntu20.04 wsl的配置参见 如果使用的window wsl安装,则关于wsl配置可参考&a…...

ASP网络求职招聘系统的设计与实现
本文主要介绍了ASP,数据库等相关知识,同时较为详尽的阐述了网络求职招聘系统的实现。本系统是使用基于HTML语言,嵌套JavaScript源代码的ASP编程技术来开发,并以IIS为服务平台实现网络求职招聘系统的构建。后台数据库选用的是ACCES…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...

自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...

麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...