小学生也能看懂的ArrayList底层原理
阅读指引:本文包含源码,如果不想阅读源码,建议跳过 “ArrayList 的主要方法” 中的源码分析部分,直接看每一部分的小总结。
简单介绍
ArrayList是 Java 集合框架中比较常用的数据结构,底层基于数组实现,能够实现容量的动态变化。
我们之所以使用它,与它能够自由添加、删除元素有关,使用者不用考虑数组的容量、遍历等问题,可以说是一个功能强大、使用简单的数组。
那么ArrayList里面到底是怎么实现的呢?
ArrayList 的成员变量
了解一个类,我们需要先了解它有哪些变量,通过这些成员变量我们能够大致了解它的实现原理。
ArrayList 的主要变量:
private static final int DEFAULT_CAPACITY = 10; //数组初始容量
transient Object[] elementData; //存放数组
private int size; //实际元素个数,指已经使用的空间数
除此之外,ArrayList 的父类也有一个重要的变量:
protected transient int modCount = 0; //记录对 List 操作的次数
看到这里,我们不着急看具体方法,让我来猜想一下 ArrayList 主要方法的实现:
add(E e)
:在数组末尾添加元素。若数组为空,则初始化数组,容量为10;若数组已满,则扩容为原来的1.5倍。get(int index)
:返回指定位置的元素。若index越界,报错。remove(Object o)
:删除第一次出现对象为 o 的元素。若 o 为 null,查找并删除值为 null 的元素;若 o 不为 null,查找并删除 o 。size()
:返回ArrayList 中已有元素数量。返回 size。
----------------------------------------------------下面是源码,慎入----------------------------------------------------------
ArrayList 的主要方法
接下来将从源码入手,分析 ArrayList 的主要方法是怎么实现的,可以先深吸一口气,我也将用比较简单的话来描述实现的过程。
1.add方法
有多种不同参数的 add() 方法,我们分析一下比较常用的add(E e):
注:代码中的中文注释是笔者添加的
public boolean add(E e) {// 检查内部容量是否充足,如果不足则扩容ensureCapacityInternal(size + 1); // Increments modCount!!// 将元素存入数组elementData[size++] = e;return true;
}private void ensureCapacityInternal(int minCapacity) {// 如果初始数组为默认空数组,minCapacity = 10if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);}// 检查是否需要扩容ensureExplicitCapacity(minCapacity);
}private void ensureExplicitCapacity(int minCapacity) {modCount++;// 添加新元素后数组长度 大于 数组当前容量if (minCapacity - elementData.length > 0)// 数组扩容,扩展为原来的 1.5 倍grow(minCapacity);
}private void grow(int minCapacity) {int oldCapacity = elementData.length;// 相当于 newCapacity = oldCapacity + oldCapacity / 2int newCapacity = oldCapacity + (oldCapacity >> 1);if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);elementData = Arrays.copyOf(elementData, newCapacity);
}
总结:
调用 add(E e) 方法,首先判断 elementData 是否为空数组,如果是空数组,初始化 elementData 容量为 10;如果不是空数组,则检查 elementData 数组是否已满,如果已满则进行扩容,扩展为原来的 1.5 倍。最后将元素 e 添加到 elementData 数组末尾。
2.get方法
该方法将 返回此列表中指定位置的元素。
public E get(int index) {// 数组下标越界检查rangeCheck(index);return elementData(index);
}private void rangeCheck(int index) {// 如果下标 大于 数组元素数量if (index >= size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}@SuppressWarnings("unchecked")
E elementData(int index) {// 返回该元素return (E) elementData[index];
}
总结
调用 get(int index) 方法,首先判断下标 index 是否越界,越界则抛异常,没越界则直接返回对应下标的元素。
3.remove方法
该方法 将删除列表中第一次出现的指定元素。
public boolean remove(Object o) {// 如果 o 为空if (o == null) {// 遍历 elementData, 找出 值为 null 的元素并删除for (int index = 0; index < size; index++)if (elementData[index] == null) {fastRemove(index);return true;}// 如果 o 不为空} else {// 遍历 elementData, 找出 值为 o 的元素并删除for (int index = 0; index < size; index++)if (o.equals(elementData[index])) {fastRemove(index);return true;}}return false;
}// 删除指定下标元素
// 让 index 后的元素整体往前 copy, 然后旧数组的最后一个元素位置赋值为 null
private void fastRemove(int index) {modCount++;int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index,numMoved);elementData[--size] = null; // clear to let GC do its work
}
总结
调用 remove(Object o)方法,需要先判断 o 是否为 null,为空则遍历 elementData,找出值为 null 的元素并删除;如果不为空,遍历 elementData,找出值为 o 的元素并删除。
结束语:每天进步一点点~
小学生也能看懂的ArrayList底层原理相关推荐
- 人人都能看懂的Spring底层原理,看完绝对不会懵逼
人人都能看懂的Spring原理,绝对不会懵逼 为什么要使用Spring? Spring的核心组件 Spring是如何实现IOC和DI的? 定义了BeanDefinition 扫描加载BeanDefin ...
- 10分钟看懂 Java NIO 底层原理
写在前面 很多的小伙伴,被java IO 模型,搞得有点儿晕,一会儿是4种模型,一会儿又变成了5种模型. 很多的小伙伴,也被nio这个名词搞晕了,一会儿java 的nio 不叫 非阻塞io,一会儿ja ...
- 《小学生都能看懂的快速沃尔什变换从入门到升天教程》(FWT / FMT / FMI)(最最严谨清晰的证明!零基础也能得学会!)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 0x00 卷积 0x01 多项式 0x02 卷积的定义 0x03 卷积的基本性质 0x04 位运 ...
- 小学生都能看懂的FFT!!!
小学生都能看懂的FFT!!! 前言 在创新实践中心偷偷看了一天FFT资料后,我终于看懂了一点.为了给大家提供一份简单易懂的学习资料,同时也方便自己以后复习,我决定动手写这份学习笔记. 食用指南: 本篇 ...
- 小学生都能看懂,彻底解决环境搭建难题,一步一截图,再无VMware网络难题
小学生都能看懂,彻底解决环境搭建难题,一步一截图,再无VMware网络难题 原创 韦东山 百问科技 1周前 上周四我们预告了这周要发布环境搭建的终极解决方案,经过一周的努力,终于写好了文档,Ubunt ...
- 《小学生都能看懂的生成函数从入门到升天教程》《生成函数全家桶》
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 小学生都能看懂系列 目录 0x00 生成函数 0x10 例题引入 0x11 ExampleA\tt E ...
- 《小学生都能看懂的三类斯特林数从入门到升天教程 》(含性质完整证明、斯特林反演、拉赫数)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 真的特别简单,我尽量讲的详细一些,本文包含了几乎所有性质定理证明,老少皆宜 ~ 内容过多,质量过硬,建 ...
- 《小学生都能看懂的群论从入门到升天教程》 《群论全家桶》
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 小学生都能看懂系列,小学生:我太难了 群论.置换.Bunrnside引理.Pόlya定理等概念是群 ...
- ArrayList底层原理
ArrayList底层原理 ArrayList在工作中经常用到,今天来看一下ArrayList的底层是如何实现的?在这之前,先抛出几个问题. 1.ArrayList底层实现的数据结构是什么? 2.Ar ...
最新文章
- poj2002 hash+数学
- 【爬坑】远程连接 MySQL 失败
- 表达式求值及转换算法
- 还发愁项目经验吗?基于Netty实现分布式RPC框架[附完整代码]
- oopc——1.抽象
- 【汇编语言】子程序结构
- 方向余弦,向量夹角,向量的投影
- 家用电器行业十二月行业动态报告:11月冰洗表现亮眼,空调价格回升持续(20201231).PDF
- 瞎琢磨先生のJava笔记之读取SpringBoot配置文件的几种方式
- python中 math.isfinite返回值为false_带有Python示例的math.isfinite()方法
- 用citespace对知网文献的关键词分析结果很少如何解决?
- 住房公积金约定提取业务问答
- 01.朴素贝叶斯介绍
- linux 磁盘碎片整理
- Day13-Java方法详解,方法的定义、重载,命令行传参,可变参数与递归
- 19朵玫瑰花的花语-教你简单玫瑰花的折法
- MATLAB官方权威免费视频教程(入门+深度学习)
- 用友软件首席架构师 黄义璋
- 工业机器视觉系统的构成与开发过程(理论篇—1)
- c语言入门for语句,c语言for语句