对Java ArrayList的自动扩容机制示例讲解
作者:ZERONELOVE 时间:2022-04-09 07:58:25
注意:
不同的JDK版本的扩容机制可能有差异
实验环境:JDK1.8
扩容机制:
当向ArrayList中添加元素的时候,ArrayList如果要满足新元素的存储超过ArrayList存储新元素前的存储能力,ArrayList会增强自身的存储能力,已达到存储新元素的要求
ArrayList:本质通过内部维护的数组对象进行数据存储
①:分析ArrayList的add(E)方法
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
分析:add方法首先通过ensureCapacityInternal()方法确保当前ArrayList维护的数组具有存储新元素的能力,经过处理之后将元素存储在数组elementData的尾部
elementData:ArrayList真正用于存储元素的数组
②:分析ensureCapacityInternal方法
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
分析:ensureCapacityInternal判断ArrayList默认的元素存储数据是否为空,为空则设置最小要求的存储能力为必要存储的元素和默认存储元素个数的两个数据之间的最大值,然后调用ensureExplicitCapacity方法实现这种最低要求的存储能力
注意:ArrayList的存储空间并不是需要一个创建一个,而是分阶段性的创建,一般会预留存储空间。
例如,如果ArrayList需要存储10个元素,恰好ArrayList只能存储6个元素,剩余4个元素无法存储,ArrayList可能会一次性扩展10个元素,这种ArrayList就有20个元素的存储能力,在存储能力范围内,下次再存放元素,就不需要再次扩容
③:分析ensureExplicitCapacity方法:
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
分析:如果最低要求的存储能力>ArrayList已有的存储能力,这就表示ArrayList的存储能力不足,因此需要调用 grow();方法进行扩容
④:分析grow()方法
private void grow(int minCapacity) {
// overflow-conscious code
int 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);
}
分析:当ArrayList扩容的时候,首先会设置新的存储能力为原来的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
如果扩容之后还是不能满足要求则MAX_ARRAY_SIZE比较,求取最大值,
如果MAX_ARRAY_SIZE大小的能力还是不能满足则通过hugeCapacity()方法获取ArrayList能允许的最大值:
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
从hugeCapacity方法看出,ArrayList最大的存储能力:存储元素的个数为整型的范围。
确定ArrayList扩容之后最新的可存储元素个数时,调用
elementData = Arrays.copyOf(elementData, newCapacity);
实现elementData数组的扩容,整个流程就是ArrayList的自动扩容机制工作流程
扩展:
ArrayList的自动扩容机制底层借助于System实现
public static native void arraycopy
(Object src, int srcPos,
Object dest, int destPos,
int length);
arraycopy标识为native意味JDK的本地库,不可避免的会进行IO操作,如果频繁的对ArrayList进行扩容,毫不疑问会降低ArrayList的使用性能,因此当我们确定添加元素的个数的时候,我们可以事先知道并指定ArrayList的可存储元素的个数,这样当我们向ArrayList中加入元素的时候,就可以避免ArrayList的自动扩容,从而提高ArrayList的性能
ArrayList含参构造函数:初始化时指定存储元素的能力:
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException(
"Illegal Capacity: "+initialCapacity);
}
}
来源:https://blog.csdn.net/yang1464657625/article/details/59109133
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Java设计模式之备忘录模式实现对象状态的保存和恢复
![](https://img.aspxhome.com/file/2023/9/58439_0s.png)
IDEA的Swing可视化插件JFormDesigner详解
![](https://img.aspxhome.com/file/2023/6/62996_0s.jpg)
java注解结合aspectj AOP进行日志打印的操作
![](https://img.aspxhome.com/file/2023/3/65783_0s.jpg)
用java WebSocket做一个聊天室
![](https://img.aspxhome.com/file/2023/2/60392_0s.jpg)
Java基础之详解HashSet的使用方法
![](https://img.aspxhome.com/file/2023/7/57727_0s.png)
SpringIOC框架的简单实现步骤
详解Java实现缓存(LRU,FIFO)
![](https://img.aspxhome.com/file/2023/1/64101_0s.png)
Java通过PropertyDescriptor反射调用set和get方法
浅谈byte和长度为8的boolean数组互相转换
dubbo入门指南及demo实例详解
![](https://img.aspxhome.com/file/2023/6/67166_0s.jpg)
spring boot集成smart-doc自动生成接口文档详解
![](https://img.aspxhome.com/file/2023/3/60773_0s.png)
Jenkins Pipeline 部署 SpringBoot 应用的教程详解
![](https://img.aspxhome.com/file/2023/0/61240_0s.png)
spring mvc中直接注入的HttpServletRequst安全吗
![](https://img.aspxhome.com/file/2023/6/63506_0s.png)
Java实现简单登陆界面
![](https://img.aspxhome.com/file/2023/8/63398_0s.png)
Java使用Thread和Runnable的线程实现方法比较
SpringBoot配置拦 截器实现过程详解
教你使用Java获取当前时间戳的详细代码
详解Java单元测试之Junit框架使用教程
![](https://img.aspxhome.com/file/2023/8/61788_0s.png)
Spring Boot学习入门之AOP处理请求详解
SpringBoot使用@ResponseBody返回图片的实现
![](https://img.aspxhome.com/file/2023/4/60414_0s.jpg)