ArrayList原理分析(重点在于扩容)
2024-09-04 11:57:28
首先,ArrayList定义只定义类两个私有属性:
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer.
*/
private transient Object[] elementData; /**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;
可知:elementData存储ArrayList内的元素,size表示它包含的元素的数量(不是指容量)。
注意:elementData用transient修饰,这表明当持久化ArrayList对象时,并不会保存它。
ArrayList是基于数组实现的,添加元素时,将某个位置的值设置为指定元素即可,但数组容量不够,如何扩容呢?
我们提供具体的方法来分析:
add方法:
// 将指定的元素添加到此列表的尾部。
public boolean add(E e) {
ensureCapacity(size + 1); //判断容量是否足够,不够就扩容
elementData[size++] = e;
return true;
}
那么扩容的核心在于ensureCapacity方法
ensureCapacity方法:
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) { //size+1即添加后的长度,判断如果添加,会不会过长
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1; //1.5倍扩容
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity); //将老数组拷贝一份到新数组
}
}
可知:
1. 每次添加前都会判断是否会过长,会,则先扩容
2. 每次扩容都是1.5倍扩容,其实是1.5倍+1。
3. 老数组通过Arrays.copyOf()拷贝一份到新数组
那么问题来了,每次扩容都是1.5倍是否会造成较大的空间浪费?
是的,所以建议在构造ArrayList实例时,就预估大小并指定其容量,以避免数组扩容的发生。或者根据实际需求,直接调用ensureCapacity方法来手动增加ArrayList实例的容量。
最新文章
- [转]thinkphp 模板显示display和assign的用法
- 用php生成一个excel文件(原理)
- PCA9554
- 『c++』 模板(template)--- 参数化多态性
- csharp: DataTable Rename ColumnName and remove Column
- CORDIC原理与FPGA实现(1)
- 利用JAXB实现java实体类和xml互相转换
- php核心知识要点
- SignalR Troubleshooting
- destoon实现调用当前栏目分类及子分类和三级分类的方法
- OpenMeetings(3)----启动顺序解析
- Mac OS下SVN的使用:服务的和客户端
- Dragon Balls
- Spring MVC简单原理
- MQTT报文格式
- [模板] 区间mex &;&; 区间元素种数
- DAG路径覆盖模型
- JavaSE| 面向对象-类的五大成员
- 用python实现数学多元数学方程式计算
- 利用jQuery进行三行两列等高布局