ArrayList扩容源码分析
2022/2/23 11:52:24
本文主要是介绍ArrayList扩容源码分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
ArrayList扩容源码分析
结论
-
实际是维护了一个Object类型的数组(transient Object[] elementData)
transient表示瞬时,表示该属性不会被序列化
-
创建ArrayList时,调用无参构造时
初始elementData容量为0,第一次添加时,扩容至10
如果需要再次扩容时,则扩容为1.5倍
-
创建ArrayList时,调用指定大小的构造器时
初始elementData容量为指定大小
如果需要再次扩容时,则扩容为1.5倍
分析源码:
无参构造时的扩容
无参构造
public ArrayList() { private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 创建了一个空的elementData this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
说明第一次初始化时容量为0
添加方法add()
public boolean add(E e) { // 扩容 ensureCapacityInternal(size + 1); // Increments modCount!! // 再添加 elementData[size++] = e; // 100%返回true return true; }
确认容量ensureCapacityInternal()
protected transient int modCount = 0; private static final int DEFAULT_CAPACITY = 10; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // ensureCapacityInternal() // 此时参数为size + 1 private void ensureCapacityInternal(int minCapacity) { // 调用函数 // ensureExplicitCapacity() // 将calculateCapacity(elementData, minCapacity)的返回值作为参数 ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } // calculateCapacity() // 用于确定一个minCapacity private static int calculateCapacity(Object[] elementData, int minCapacity) { // 如果elementData等于空 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 返回一个DEFAULT_CAPACITY 和 minCapacity比较出的最大值 // private static final int DEFAULT_CAPACITY = 10; // 也就是说minCapacity<10时,返回的是10 return Math.max(DEFAULT_CAPACITY, minCapacity); } // minCapacity>10时,返回的是minCapacity return minCapacity; } // ensureExplicitCapacity() // 此时minCapacity为calculateCapacity()返回值 // size+1<10时,返回的是10 // size+1>10时,返回的是size+1 private void ensureExplicitCapacity(int minCapacity) { // 记录当前集合被修改的次数 // 多线程修改时会抛出异常 modCount++; // overflow-conscious code // 当minCapacity大于当前elementData长度时 if (minCapacity - elementData.length > 0) // 扩容 // 调用grow() // 参数为minCapacity grow(minCapacity); } // grow() private void grow(int minCapacity) { // overflow-conscious code // elementData数组长度 // 第一次进来是0 int oldCapacity = elementData.length; // 用elementData数组长度+elementData数组长度右移一位(正数是相当于除以2)赋给新容器 // 也就是原来elementData数组长度的1.5倍 // 第一次是0 // 第一次没有真正的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); // 如果minCapacity比newCapacity大 // 第一次0 - 10 < 0 if (newCapacity - minCapacity < 0) // 那就将minCapacity赋给newCapacity // 第一次newCapacity为10 newCapacity = minCapacity; // 如果newCapacity 比 MAX_ARRAY_SIZE大 // @Native public static final int MAX_VALUE = 0x7fffffff; // private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // MAX_ARRAY_SIZE 是 0x7fffffff - 8 // 2的31次方-1-8 // newCapacity比最大容量还大的话 // 一般不会 if (newCapacity - MAX_ARRAY_SIZE > 0) // 比最大容量还大的话调用hugeCapacity() newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: // 正常情况调用Arrays.copyOf() // 通过拷贝达到给elementData赋值newCapacity长度的效果 elementData = Arrays.copyOf(elementData, newCapacity); } // grow()结束到: // ensureExplicitCapacity()结束到: // ensureCapacityInternal()结束到add(): public boolean add(E e) { // 扩容 ensureCapacityInternal(size + 1); // Increments modCount!! // 赋值 elementData[size++] = e; // 100%返回true return true; } // add()结束
指定大小的构造器时的扩容
有参构造
public ArrayList(int initialCapacity) { // 如果参数 > 0 if (initialCapacity > 0) { // 创建一个长度为参数的Object[]赋给elementData this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { // 如果参数为0 // private static final Object[] EMPTY_ELEMENTDATA = {}; // 赋值空数组 this.elementData = EMPTY_ELEMENTDATA; } else { // 负数抛一个异常 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
add()
public boolean add(E e) { // 扩容 ensureCapacityInternal(size + 1); // Increments modCount!! // 再添加 elementData[size++] = e; // 100%返回true return true; }
不同在扩容的判断
private void ensureCapacityInternal(int minCapacity) { // 调用函数 // ensureExplicitCapacity() // 将calculateCapacity(elementData, minCapacity)的返回值作为参数 ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } // calculateCapacity() // 用于确定一个minCapacity private static int calculateCapacity(Object[] elementData, int minCapacity) { // 如果elementData等于空 // 此时不为空 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 不走这一步 return Math.max(DEFAULT_CAPACITY, minCapacity); } // 返回的是size+1 return minCapacity; } // ensureExplicitCapacity() // 此时minCapacity为calculateCapacity()返回值 // 返回的是size+1 private void ensureExplicitCapacity(int minCapacity) { // 记录当前集合被修改的次数 // 多线程修改时会抛出异常 modCount++; // overflow-conscious code // 当minCapacity大于当前elementData长度时 // 初始够用就不扩,不够用就进 if (minCapacity - elementData.length > 0) // 扩容 // 调用grow() // 参数为minCapacity grow(minCapacity); } // grow() private void grow(int minCapacity) { // elementData数组长度 int oldCapacity = elementData.length; // 用elementData数组长度+elementData数组长度右移一位(正数是相当于除以2)赋给新容器 // 也就是原来elementData数组长度的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); // 如果minCapacity比newCapacity大 if (newCapacity - minCapacity < 0) // 那就将minCapacity赋给newCapacity newCapacity = minCapacity; // 如果newCapacity 比 MAX_ARRAY_SIZE大 // newCapacity比最大容量还大的话 // 一般不会 if (newCapacity - MAX_ARRAY_SIZE > 0) // 比最大容量还大的话调用hugeCapacity() newCapacity = hugeCapacity(minCapacity); // 正常情况调用Arrays.copyOf() // 通过拷贝达到给elementData赋值newCapacity长度的效果 elementData = Arrays.copyOf(elementData, newCapacity); } // grow()结束到: // ensureExplicitCapacity()结束到: // ensureCapacityInternal()结束到add(): public boolean add(E e) { // 扩容 ensureCapacityInternal(size + 1); // Increments modCount!! // 赋值 elementData[size++] = e; // 100%返回true return true; } // add()结束
这篇关于ArrayList扩容源码分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南