阅读指引:本文包含源码,如果不想阅读源码,建议跳过 “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底层原理相关推荐

  1. 人人都能看懂的Spring底层原理,看完绝对不会懵逼

    人人都能看懂的Spring原理,绝对不会懵逼 为什么要使用Spring? Spring的核心组件 Spring是如何实现IOC和DI的? 定义了BeanDefinition 扫描加载BeanDefin ...

  2. 10分钟看懂 Java NIO 底层原理

    写在前面 很多的小伙伴,被java IO 模型,搞得有点儿晕,一会儿是4种模型,一会儿又变成了5种模型. 很多的小伙伴,也被nio这个名词搞晕了,一会儿java 的nio 不叫 非阻塞io,一会儿ja ...

  3. 《小学生都能看懂的快速沃尔什变换从入门到升天教程》(FWT / FMT / FMI)(最最严谨清晰的证明!零基础也能得学会!)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 0x00 卷积 0x01 多项式 0x02 卷积的定义 0x03 卷积的基本性质 0x04 位运 ...

  4. 小学生都能看懂的FFT!!!

    小学生都能看懂的FFT!!! 前言 在创新实践中心偷偷看了一天FFT资料后,我终于看懂了一点.为了给大家提供一份简单易懂的学习资料,同时也方便自己以后复习,我决定动手写这份学习笔记. 食用指南: 本篇 ...

  5. 小学生都能看懂,彻底解决环境搭建难题,一步一截图,再无VMware网络难题

    小学生都能看懂,彻底解决环境搭建难题,一步一截图,再无VMware网络难题 原创 韦东山 百问科技 1周前 上周四我们预告了这周要发布环境搭建的终极解决方案,经过一周的努力,终于写好了文档,Ubunt ...

  6. 《小学生都能看懂的生成函数从入门到升天教程》《生成函数全家桶》

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 小学生都能看懂系列 目录 0x00 生成函数 0x10 例题引入 0x11 ExampleA\tt E ...

  7. 《小学生都能看懂的三类斯特林数从入门到升天教程 》(含性质完整证明、斯特林反演、拉赫数)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 真的特别简单,我尽量讲的详细一些,本文包含了几乎所有性质定理证明,老少皆宜 ~ 内容过多,质量过硬,建 ...

  8. 《小学生都能看懂的群论从入门到升天教程》 《群论全家桶》

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 小学生都能看懂系列,小学生:我太难了   群论.置换.Bunrnside引理.Pόlya定理等概念是群 ...

  9. ArrayList底层原理

    ArrayList底层原理 ArrayList在工作中经常用到,今天来看一下ArrayList的底层是如何实现的?在这之前,先抛出几个问题. 1.ArrayList底层实现的数据结构是什么? 2.Ar ...

最新文章

  1. poj2002 hash+数学
  2. 【爬坑】远程连接 MySQL 失败
  3. 表达式求值及转换算法
  4. 还发愁项目经验吗?基于Netty实现分布式RPC框架[附完整代码]
  5. oopc——1.抽象
  6. 【汇编语言】子程序结构
  7. 方向余弦,向量夹角,向量的投影
  8. 家用电器行业十二月行业动态报告:11月冰洗表现亮眼,空调价格回升持续(20201231).PDF
  9. 瞎琢磨先生のJava笔记之读取SpringBoot配置文件的几种方式
  10. python中 math.isfinite返回值为false_带有Python示例的math.isfinite()方法
  11. 用citespace对知网文献的关键词分析结果很少如何解决?
  12. 住房公积金约定提取业务问答
  13. 01.朴素贝叶斯介绍
  14. linux 磁盘碎片整理
  15. Day13-Java方法详解,方法的定义、重载,命令行传参,可变参数与递归
  16. 19朵玫瑰花的花语-教你简单玫瑰花的折法
  17. MATLAB官方权威免费视频教程(入门+深度学习)
  18. 用友软件首席架构师   黄义璋
  19. 工业机器视觉系统的构成与开发过程(理论篇—1)
  20. c语言入门for语句,c语言for语句

热门文章

  1. sublime 常用快捷键
  2. Windows xp下IDT Hook和GDT的学习
  3. IP地址在数据库里面的存储方式
  4. C# 获取Get请求返回
  5. iOS插件化研究之一——JavaScriptCore
  6. SpringBoot 入门知识点详解
  7. 那年学过的Java笔记一SE基础
  8. python语法(一)——判断字符串是否包含某子字符串
  9. Linux下安装vim
  10. 敲重点,数据需要这么做才能成为资产