深入理解ArrayList的动态扩容机制及应用

在java编程中,数据结构起着至关重要的作用,而ArrayList作为一种常用的动态数组,为我们在处理数据时提供了便利。其中,其独特的动态扩容机制更是为其赢得了广泛的应用。我们不管在工作还是面试中,都会遇到ArrayList,本文将深入探讨ArrayList的动态扩容机制,以便我们在工作或者面试中用到。

ArrayList简介

ArrayList是Java编程语言中的一个类,它实现了List接口,底层通过数组来存储元素。提供了对List 的添加(add)、删除(remove)、获取元素(get)等功能。其缺点是元素必须连续存储,所以增删慢,优点是查询快。ArrayList具有动态扩容的特性,这意味着它能够根据需要自动调整内部数组的大小,以适应不同数量的元素。

动态扩容详解

当我们向ArrayList 中添加元素(调用add()或者addAll())时,都调用了一个ensureCapacityInternal()方法

我们来看源码:

add()

public boolean add(E e) {ensureCapacityInternal(size + 1);  // Increments modCount!!elementData[size++] = e;return true;
}

addAll()

public boolean addAll(Collection<? extends E> c) {Object[] a = c.toArray();int numNew = a.length;ensureCapacityInternal(size + numNew);  // Increments modCountSystem.arraycopy(a, 0, elementData, size, numNew);size += numNew;return numNew != 0;
}

从源码可以看到,这两个方法都调用了ensureCapacityInternal()这个方法,参数是当前list的长度加上要插入的对象给个个数(单个对象的话为1,对象集合的话是集合的长度),既集合添加元素所需最小的长度

ensureCapacityInternal()

private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

ensureExplicitCapacity() 方法的入参是calculateCapacity()(参数是存储实际元素的数组和集合添加元素所需最小的长度) 方法处理后的值。

calculateCapacity()

private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;
}

当前方法返回的值是如果源集合是空的,则返回 默认容量(10)和元素集合添加元素所需最小的长度值比较,值大的一个,若不为空则返回minCapacity。

_20230828230112.png

ensureExplicitCapacity()

private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0)grow(minCapacity);
}

grow

private void grow(int minCapacity) {// overflow-conscious codeint 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);
}

我们来详细解读下这段代码

  • int oldCapacity = elementData.length;

获取当前数组的容量,也就是elementData数组的长度,即当前存储元素的数组长度。

  • int newCapacity = oldCapacity + (oldCapacity >> 1);

计算新的容量。这里使用位运算右移1位(相当于除以2)的方式,将当前容量扩大1.5倍。
如果对 位运算符 >> 不太了解对的家人们可以看下我们上篇文章 深入解析Java中的位运算符:<<、>>和>>>

  • if (newCapacity - minCapacity < 0)

检查计算得到的新容量是否满足最小容量要求。如果不满足,则将新容量设置为最小容量minCapacity。

  • if (newCapacity - MAX_ARRAY_SIZE > 0)

检查新容量是否超过了最大数组容量限制。MAX_ARRAY_SIZE是ArrayList内部定义的一个常量,表示数组的最大容量。如果新容量超过这个限制,就调用hugeCapacity(minCapacity)方法来获得一个足够大的容量。

_20230828230251.png

_20230828230304.png

  • elementData = Arrays.copyOf(elementData, newCapacity);

使用Arrays.copyOf()方法将原有的elementData数组复制到一个新数组中,新数组的容量为计算得到的新容量newCapacity。这实现了实际的数组扩容操作。

使用注意事项和优化

  • 初始化大小

在创建ArrayList时,如果我们能够预测大致的数据量,初始化一个合适的初始大小可以减少扩容次数,从而提高性能。

  • 避免频繁扩容

频繁的扩容会带来较大的性能开销,因此尽量避免在循环中多次添加元素,以免触发多次扩容操作。

总结

ArrayList作为一种常用的数据结构,在动态扩容机制的支持下,为我们的编程工作带来了很大的便利。深入理解其动态扩容的原理和应用场景,有助于我们更好地在工作中使用ArrayList,同时在面试中也能够展现出扎实的基础知识。

无论是处理不确定数据量的业务逻辑,还是在技术面试中回答ArrayList相关问题,对其动态扩容机制的理解都将让你更加从容应对各种挑战。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/87832.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【腾讯云 TDSQL-C Serverless 产品测评】- 云原生时代的TDSQL-C MySQL数据库技术实践

一、活动介绍&#xff1a; “腾讯云 TDSQL-C 产品测评活动”是由腾讯云联合 CSDN 推出的针对数据库产品测评及产品体验活动&#xff0c;本次活动主要面向 TDSQL-C Serverless版本&#xff0c;初步的产品体验或针对TDSQL-C产品的自动弹性能力、自动启停能力、兼容性、安全、并发…

使用ctcloss训练矩阵生成目标字符串

首先我们需要明确 c t c l o s s ctcloss ctcloss是用来做什么的。比如说要生成的目标字符串长度为 l l l&#xff0c;而这个字符串包含 s s s个字符&#xff0c;字符串允许的最大长度为 L L L&#xff0c;这里认为一个位置是一个时间步&#xff0c;就是一拍&#xff0c;记为 T…

9个至少提升50%效率的VSCODE插件

在开始编码之前&#xff0c;您首先需要让您的工作流程适合您。让它更高效、更漂亮、更可定制。它会节省您大量的时间和精力&#xff0c;因此您将有更多的能力进行编码。 无论您是前端还是后端开发人员还是高级 Java 程序员&#xff0c;都没关系。这篇文章对你们大多数人来说仍然…

【rust/egui】(六)看看template的app.rs:TextEdit

说在前面 rust新手&#xff0c;egui没啥找到啥教程&#xff0c;这里自己记录下学习过程环境&#xff1a;windows11 22H2rust版本&#xff1a;rustc 1.71.1egui版本&#xff1a;0.22.0eframe版本&#xff1a;0.22.0上一篇&#xff1a;这里 TextEdit 文本编辑框 其定义为&#…

干货!证书超实用小Tips

1.CSA 是加拿大标准协会(Canadian Standards Association)的简称&#xff0c;它成立于1919年&#xff0c;是加拿大首家专为制定工业标准的非盈利性机构。在北美市场上销售的电子、电器等产品都需要取得安全方面的认证。 2.EAC认证 是海关联盟国家的认证。海关联盟是由俄罗斯…

【java】【springboot】【idea】springboot项目pom.xml 灰色下划线

解决方案&#xff1a; 这里我们找到了原因&#xff0c;就是因为选择了Ignored Files导致pom.xml文件被设置在maven忽略文件清单中&#xff0c;所以我们将打勾的选项取消&#xff0c;点击Apply,然后点击OK

Flutter问题记录 - Unable to find bundled Java version

新版本的Android Studio真的移除了JRE&#xff0c;jre目录找不到&#xff0c;怪不得报错了&#xff0c;不过多了一个jbr目录&#xff0c;找了个以前的Android Studio版本对比 搜了一下jbr&#xff08;JetBrains Runtime&#xff09;&#xff0c;原来IDEA老早就开始用了&#xf…

视频汇聚/视频云存储/视频监控管理平台EasyCVR安全检查的相关问题及解决方法

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

Python使用 YOLO_NAS_S 模型进行目标检测并保存预测到的主体图片

一、前言&#xff1a; 使用 YOLO_NAS_S 模型进行目标检测&#xff0c;并保存预测到的主体图片 安装包&#xff1a; pip install super_gradients pip install omegaconf pip install hydra-core pip install boto3 pip install stringcase pip install typing-extensions pi…

自动化PLC工程师能否转到c#上位机开发?

成功从自动化PLC工程师转向C#上位机开发的经历可能因人而异&#xff0c;以下是一些分享的思路和建议&#xff1a;扩展编程技能&#xff1a;学习C#语言和相关的开发工具和框架&#xff0c;掌握语言的基础知识和常用的编程技巧。可以通过在线教程、培训课程、书籍等途径进行学习&…

python使用 flask+vue 制作前后端分离图书信息管理系统

目录标题 前言制作前后端分离图书信息管理系统的思路&#xff1a;素材代码效果展示 后端部分接口部分前端部分尾语 前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 哈喽兄弟们&#xff0c;今天咱们来用Python实现一个前后端分离的图书信息管理系统。 制作前后端分离图书信…

RabbitMQ的镜像队列

镜像队列 如果 RabbitMQ 集群中只有一个 Broker 节点&#xff0c;那么该节点的失效将导致整体服务的临时性不可用&#xff0c;并且也可能会导致消息的丢失。可以将所有消息都设置为持久化&#xff0c;并且对应队列的durable 属性也设置为 true &#xff0c;但是这样仍然无法…