目录
- 一、知识点回顾
- 二、ArrayList 的 add() 和 remove() 的实现
- 2.1 list.add(e) 实现原理
- 2.2 list.remove() 实现原理
ArrayList的底层是通过
数组
实现的。
一、知识点回顾
数组特点:
- 存储区间是连续的,且占用内存严重,空间复杂度很大,时间复杂度为 O(1)。
- 优点: 随机读取效率很高,原因是数组是连续的(随机访问性强,查找速度快)。
- 缺点: 插入和删除效率低,因插入数据,这个位置后面的数据要在内存中后移,且大小固定,不易动态扩展。
二、ArrayList 的 add() 和 remove() 的实现
2.1 list.add(e) 实现原理
- 第 1 步,首先判断当前size+1,是否超出数组的最小容量10:
- 如果没有超出最小容量10,则将10作为所需的最小容量;
- 如果超出最小容量10,则将size+1作为最需的最小容量。
- 第 2 步,判断所需最小容量是否大于数组的实际容量(length):
- 如果所需最小容量 > 数组的实际容量,则
需要扩容
:- 调用
grow()
方法,判断所需的最小容量是否超过实际容量的3/2(向上取整,length = length + length >> 1):- 如果所需最小容量 > 实际容量的3/2,则采用所需最小容量作为新容量;
- 如果所需最小容量 ≤ 实际容量的3/2,则采用实际容量的3/2作为新容量。
- 判断新容量是否超出 Integer.MAX_VALUE - 8:
- 如果新容量 > Integer.MAX_VALUE - 8,根据所需最小容量重新计算;
- 判断所需最小容量是否小于0:
- 如果所需最小容量 < 0,则抛出内存溢出异常:
OutOfMemoryError
。
- 如果所需最小容量 < 0,则抛出内存溢出异常:
- 判断所需最小容量是否超出 Integer.MAX_VALUE - 8:
- 如果所需最小容量 > Integer.MAX_VALUE - 8,则采用 Integer.MAX_VALUE 作为新容量;
- 如果所需最小容量 ≤ Integer.MAX_VALUE - 8,则采用 Integer.MAX_VALUE - 8 作为新容量。
- 判断所需最小容量是否小于0:
- 如果新容量 > Integer.MAX_VALUE - 8,根据所需最小容量重新计算;
- 将数组按照新容量扩容:
elementData = Arrays.copyOf(旧数组, 新容量)
,按照新容量创建一个新数组,然后将之前的数组内容复制到新数组中。
- 调用
- 如果所需最小容量 ≤ 数组的实际容量,则
不需要扩容
;
- 如果所需最小容量 > 数组的实际容量,则
- 第 3 步,将新增的值赋值到
elemetnData[size]
上,然后size扩容1。
2.2 list.remove() 实现原理
- 第1步,检查索引范围,判断索引是否大于等于容量大小(size):
- 如果索引 ≥ 容量大小,抛出索引越界异常:
IndexOutOfBoundsException
;
- 如果索引 ≥ 容量大小,抛出索引越界异常:
- 第 2 步,获取索引位置上的元素值;
- 第 3 步,将数组上索引位置以后的元素向前复制 1 位;
- 第 4 步,将数组末位位置值置为
null
,方便 GC 进行垃圾回收; - 第 5 步,将之前获取索引位置上的元素值进行返回。
整理完毕,完结撒花~ 🌻