ArrayList扩容机制

简介: 本章主要讲解了ArrayList的扩容机制

ArrayList扩容的本质就是计算出新的扩容数组的size后实例化,并将原有数组内容复制到新数组中去。

默认情况下,新的容量会是原容量的1.5。以JDK1.8为例说明:

一、源码讲解

publicbooleanadd(Ee) {
//判断是否可以容纳e,若能,则直接添加在末尾;若不能,则进行扩容,然后再把e添加在末尾ensureCapacityInternal(size+1); // Increments modCount!!//将e添加到数组末尾elementData[size++] =e;
returntrue;
}
// 每次在add()一个元素时,arraylist都需要对这个list的容量进行一个判断。通过ensureCapacityInternal()方法确保当前ArrayList维护的数组具有存储新元素的能力,经过处理之后将元素存储在数组elementData的尾部privatevoidensureCapacityInternal(intminCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
privatestaticintcalculateCapacity(Object[] elementData, intminCapacity) {
//如果传入的是个空数组则最小容量取默认容量与minCapacity之间的最大值if (elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
returnMath.max(DEFAULT_CAPACITY, minCapacity);
}
returnminCapacity;
}
privatevoidensureExplicitCapacity(intminCapacity) {
modCount++;
// 若ArrayList已有的存储能力满足最低存储要求,则返回add直接添加元素;如果最低要求的存储能力>ArrayList已有的存储能力,这就表示ArrayList的存储能力不足,因此需要调用grow();方法进行扩容if (minCapacity-elementData.length>0)
grow(minCapacity);
}
privatevoidgrow(intminCapacity) {
// 获取elementData数组的内存空间长度intoldCapacity=elementData.length;
// 扩容至原来的1.5倍intnewCapacity=oldCapacity+ (oldCapacity>>1);
//校验容量是否够if (newCapacity-minCapacity<0)
newCapacity=minCapacity;
//若预设值大于默认的最大值,检查是否溢出if (newCapacity-MAX_ARRAY_SIZE>0)
newCapacity=hugeCapacity(minCapacity);
// 调用Arrays.copyOf方法将elementData数组指向新的内存空间//并将elementData的数据复制到新的内存空间elementData=Arrays.copyOf(elementData, newCapacity);
}

二、面试题:ArrayList扩容机制回答

  • ArrayList扩容的本质就是计算出新扩容数组的size后实例化,并将原有数组的内容复制到新数组中去,默认扩容容量是原容量的1.5倍.
  • 当调用add方法时,首先调用ensureCapacityInternal方法,传入size+1,判断是否可以容纳元素e,若能,则直接添加到数组的末尾,若不能,则进行扩容,再把e添加在末尾
  • 扩容调用的方法为grow,newCapacity扩容至原来的1.5倍,然后检验容量是否足够,如果不够,就使用它指定要扩充的大小minCapacity,然后判断newCapacity是否大于MAX_ARRAY_SIZE,如果大于,就取Integer.MAX_VALUE
  • 最后调用Arrays.copyOf方法将elementData数组指向新的内存空间 ,并将elementData的数据复制到新的内存空间
相关文章
|
存储 缓存 负载均衡
数据库分库分表:提升系统性能的必由之路
数据库分库分表:提升系统性能的必由之路
297 1
|
算法 调度
详解操作系统的调度
详解操作系统的调度
583 0
|
1月前
|
缓存 安全 Java
Java并发性能优化|读写锁与互斥锁解析
本文深入解析Java中两种核心锁机制——互斥锁与读写锁,通过概念对比、代码示例及性能测试,揭示其适用场景。互斥锁适用于写多或强一致性场景,读写锁则在读多写少时显著提升并发性能。结合锁降级、公平模式等高级特性,助你编写高效稳定的并发程序。
114 0
|
缓存 NoSQL Java
避免缓存失效的三大杀手:缓存击穿、穿透与雪崩的解决方案
避免缓存失效的三大杀手:缓存击穿、穿透与雪崩的解决方案
911 0
|
监控 NoSQL Redis
看完这篇就能弄懂Redis的集群的原理了
看完这篇就能弄懂Redis的集群的原理了
575 0
|
10月前
|
Java 索引 容器
Java ArrayList扩容的原理
Java 的 `ArrayList` 是基于数组实现的动态集合。初始时,`ArrayList` 底层创建一个空数组 `elementData`,并设置 `size` 为 0。当首次添加元素时,会调用 `grow` 方法将数组扩容至默认容量 10。之后每次添加元素时,如果当前数组已满,则会再次调用 `grow` 方法进行扩容。扩容规则为:首次扩容至 10,后续扩容至原数组长度的 1.5 倍或根据实际需求扩容。例如,当需要一次性添加 100 个元素时,会直接扩容至 110 而不是 15。
347 4
Java ArrayList扩容的原理
|
消息中间件 中间件 程序员
分布式事务大揭秘:使用MQ实现最终一致性
本文由小米分享,介绍分布式事务中的MQ最终一致性实现,以RocketMQ为例。RocketMQ的事务消息机制包括准备消息、本地事务执行、确认/回滚消息及事务状态检查四个步骤。这种机制通过消息队列协调多系统操作,确保数据最终一致。MQ最终一致性具有系统解耦、提高可用性和灵活事务管理等优点,广泛应用于分布式系统中。文章还讨论了RocketMQ的事务消息处理流程和失败情况下的处理策略,帮助读者理解如何在实际应用中解决分布式事务问题。
1150 6
|
10月前
|
Java Spring 容器
SpringBoot读取配置文件的6种方式,包括:通过Environment、@PropertySource、@ConfigurationProperties、@Value读取配置信息
SpringBoot读取配置文件的6种方式,包括:通过Environment、@PropertySource、@ConfigurationProperties、@Value读取配置信息
2189 3
|
10月前
|
SQL 算法 关系型数据库
面试:什么是死锁,如何避免或解决死锁;MySQL中的死锁现象,MySQL死锁如何解决
面试:什么是死锁,死锁产生的四个必要条件,如何避免或解决死锁;数据库锁,锁分类,控制事务;MySQL中的死锁现象,MySQL死锁如何解决
|
存储 缓存 负载均衡
什么是CDN(内容分发网络)?
什么是CDN(内容分发网络)?
7248 7