Java中 ArrayList的扩容机制

ArrayList的扩容机制是怎样的

ArrayList的扩容机制是在当前容量不足以存储新元素时自动进行扩容。以下是ArrayList扩容机制的一般步骤:

  1. 当需要添加一个新元素到ArrayList中时,首先检查当前元素个数是否达到了数组的容量上限。如果达到了容量上限,则需要进行扩容操作。
  2. 扩容操作开始时,ArrayList会创建一个新的数组,其大小通常是当前容量的1.5倍(具体的增长因子可以根据实现而有所不同)。
  3. 接下来,ArrayList会将所有原数组中的元素复制到新数组中。

请注意,由于扩容操作涉及到创建新数组、复制元素以及销毁旧数组,这些操作的开销较大,因此频繁的扩容可能会影响性能。为了避免频繁的扩容操作,可以在创建ArrayList对象时指定一个较大的初始容量,或者在添加大量元素之前先使用ensureCapacity方法来增加ArrayList的容量。

此外,需要注意的是,ArrayList的扩容机制是自动的,你不需要显式地调用扩容方法。ArrayList会在需要时自动进行扩容,并在内部处理相关操作。

ArrayList的扩容机制具体是如何实现的?

ArrayList的扩容机制是在内部数组满时自动触发的,具体实现步骤如下:

  1. 首先,ArrayList会创建一个新的数组,新数组的长度通常是原数组长度的1.5倍。如果新数组的长度仍然小于需要的最小容量(即添加新元素后的总大小),那么ArrayList会将新数组的长度设置为需要的最小容量。

  2. 接下来,ArrayList使用System.arraycopy方法将原数组中的所有元素复制到新数组中。这个操作的时间复杂度是O(n),其中n是原数组的长度。

  3. 复制完成后,原数组将被垃圾回收器回收,ArrayList将开始使用新数组来存储元素。

  4. 最后,将需要添加的新元素添加到新数组的末尾。

这个过程是自动进行的,你不需要显式地调用任何方法来触发扩容。ArrayList内部会跟踪数组的长度和容量,并在需要时自动进行扩容。

需要注意的是,扩容操作涉及到内存分配、数据复制和垃圾回收,这些操作可能会带来一定的性能开销。因此,在使用ArrayList时,如果能够预估元素数量并设置合适的初始容量,可以避免频繁的扩容操作,从而提高性能。

另外,由于ArrayList是基于索引的数据结构,它在扩容后需要保持元素的顺序不变,因此无法像链表那样简单地通过改变指针来实现扩容。这也是ArrayList扩容操作相对复杂的原因之一。

ArrayList的扩容机制的实现代码

ArrayList的扩容机制的实现代码位于Java的ArrayList类中,特别是grow方法中。以下是ArrayList类中与扩容相关的部分代码片段:

/*** The size of the ArrayList (the number of elements it contains).*/
private int size;/*** The capacity of the ArrayList (the number of elements it can contain before growing).*/
private int capacity;/*** The array buffer into which the elements of the ArrayList are stored.* The capacity of the ArrayList is the length of this array buffer. Any empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA* will be expanded to DEFAULT_CAPACITY when the first element is added.*/
private transient Object[] elementData;// .../*** Increases the capacity of this ArrayList instance, if necessary,* to ensure that it can hold at least the number of elements specified by* the minimum capacity argument.** @param   minCapacity   the desired minimum capacity*/
public void ensureCapacity(int minCapacity) {int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)// any size if real elementData is used? 0// larger than default for using object array: DEFAULT_CAPACITY;if (minCapacity > minExpand) {ensureExplicitCapacity(minCapacity);}
}private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0)grow(minCapacity);
}/*** Increases the capacity to ensure that it can hold at least the* number of elements specified by the minimum capacity argument.** @param minCapacity the desired minimum capacity*//
private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5 * oldCapacityif (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);
}// .../*** Returns a capacity at least as large as the given minimum capacity.** @param minCapacity the desired minimum capacity* @return a capacity at least as large as minCapacity*/
private static int hugeCapacity(int minCapacity) {if (minCapacity < 0) // overflowthrow new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE)? Integer.MAX_VALUE: MAX_ARRAY_SIZE;
}

在上面的代码中,ensureCapacity方法用于确保ArrayList至少有指定的最小容量。如果当前容量不足,它将调用grow方法来扩展容量。grow方法计算新的容量,通常是旧容量的1.5倍(oldCapacity + (oldCapacity >> 1)),但也会确保新容量至少等于所需的最小容量。如果新容量超过了MAX_ARRAY_SIZE(一个很大的值,通常是Integer.MAX_VALUE),则使用hugeCapacity方法来处理。

Arrays.copyOf方法用于创建新数组并复制旧数组的内容到新数组。最后,elementData引用被更新为指向新数组,旧数组将由垃圾回收器回收。

注意,ArrayList的扩容机制可能会因为Java版本的不同而略有差异,但基本的思路和实现方式是相似的。

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

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

相关文章

【MySQL进阶之路】亿级数据量表SQL调优实战

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…

智能车折线电磁组学习资料

LQ_STC32G12K128核心板资料 链接:https://pan.baidu.com/s/1DWlhqX98dJczm35FNBYOBQ?pwd=pmc0 提取码:pmc0 LQ_STC32G12K128母板资料 链接:https://pan.baidu.com/s/1msFPIxXQaLJ5R1Mt0WANVA 提取码:7n9cLQ_STC32G12K128母板原理图资料 链接:https://pan.baid…

Swift Combine 发布者订阅者操作者 从入门到精通二

Combine 系列 Swift Combine 从入门到精通一 1. Combine核心概念 你只需要了解几个核心概念&#xff0c;就能使用好 Combine&#xff0c;但理解它们非常重要。 这些概念中的每一个都通过通用协议反映在框架中&#xff0c;以将概念转化为预期的功能。 这些核心概念是&#x…

通过增加缓存优化斐波那契递归的冗余计算

一、python 斐波那契数列的递归实现存在大量的冗余计算。例如&#xff0c;为了计算fib(n)&#xff0c;我们需要计算fib(n-1)和fib(n-2)&#xff0c;但是在计算fib(n-1)的过程中&#xff0c;我们又会重复计算fib(n-2)。当n的值很大时&#xff0c;这种冗余计算会消耗大量的计算资…

肿瘤微环境异质性对治疗反应的影响(综述)

Influence of tumour micro-environment heterogeneity on therapeutic response | Nature 肿瘤的形成涉及肿瘤细胞与细胞外基质、肿瘤血管和免疫细胞的共同进化。肿瘤的成功生长和最终转移并不完全取决于肿瘤细胞的基因改变&#xff0c;还取决于这种突变在特定环境中带来的适…

AMD FPGA设计优化宝典笔记(3)控制集

控制集 1 控制集的个数要求 控制集 control set&#xff1a;因为 7 系列 FPGA&#xff0c;一个 slice 只能有一种控制集&#xff08;触发器的使用方式 比如有复位/有时钟使能等等&#xff09;&#xff0c;多了就会分布到不同的 slice 里&#xff0c; 所以代码尽量统一触发器的…

2.12 分支、循环练习

1、选择题 1.1、以下程序的输出结果是 A 。 main() { int k11,k22,k33,x15; if(!k1) x--; else if(k2) if(k3) x4; else x3; printf(“x%d\n”,x); } A x4 B x15 C x14 D x3 解析&#xff1a;if(!k1) x--; 检查 k1 是否为0。因为 k1 的值为1&#xff0c;所…

带你了解软件系统架构的演变

软件系统架构的演变是一个不断适应技术进步和业务需求变化的过程。从早期的单体架构到现代的微服务架构&#xff0c;软件架构经历了几个主要的演变阶段。以下是对这些演变阶段的概述&#xff0c;以及一些工作实践、项目复盘和职场感悟。 单体架构&#xff08;Monolithic Archi…

嵌入式Qt Qt Creator安装与工程介绍

一.Qt概述 什么是Qt&#xff1a;Qt是一个跨平台的C图形用户界面应用程序框架。它为应用程序开发者提供建立图形界面所需的所有功能。它是完全面向对象的&#xff0c;很容易扩展&#xff0c;并且允许真正的组件编程。 二.Qt Creator下载安装 下载地址&#xff1a;Index of /a…

如何编译zlib?

学习文章&#xff1a;windows zlib库编译步骤_nmake 编译 zlib-CSDN博客 记录关键步骤&#xff1a; 打开 执行&#xff1a; 先cd到该目录&#xff1a; C:\Users\xxx\Downloads\zlib-1.2.11\contrib\masmx86 (这是我的zlib源码的下载路径&#xff09; 执行bld_ml32.bat 再…

【每日一题】03 不同路径Ⅱ(DP2)

问题描述 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物。那么从左上…

LeetCode.145. 二叉树的后序遍历

题目 145. 二叉树的后序遍历 分析 上篇文章我们讲了前序遍历&#xff0c;这道题目是后序遍历。 首先要知道二叉树的后序遍历是什么&#xff1f;【左 右 根】 然后利用递归的思想&#xff0c;就可以得到这道题的答案&#xff0c;任何的递归都可以采用 栈 的结构来实现&#…

Python||数据分析之pyecharts 绘图(词云、气泡)

1. echarts 和 Pyecharts 简介 1.1echarts 简介: • echarts 是一个使用 JavaScript 实现的开源可视化库,涵盖各行业图表,满足各种需求。 • echarts 遵循 Apache-2.0 开源协议,免费商用。 • ECharts 最初由百度团队开源,并于 2018 年初捐赠给 Apache 基金会,成为 AS…

速盾cdn:cdn布置节点需要服务器吗

CDN&#xff08;Content Delivery Network&#xff09;是一种通过在全球各地分布的服务器节点存储和传送静态和动态内容的系统。在CDN中&#xff0c;服务器节点被称为边缘节点&#xff0c;它们位于全球不同的地理位置&#xff0c;可以更接近最终用户&#xff0c;从而提供更快的…

【Tauri】(2):使用Tauri应用开发,使用开源的Chatgpt-web应用做前端,使用rust 的candle做后端,本地运行小模型桌面应用

视频演示地址 https://www.bilibili.com/video/BV17j421X7Zc/ 【Tauri】&#xff08;2&#xff09;&#xff1a;使用Tauri应用开发&#xff0c;使用开源的Chatgpt-web应用做前端&#xff0c;使用rust 的candle做后端&#xff0c;本地运行小模型桌面应用 1&#xff0c;做一个免…

自定义Exporter开发--实现自己应用的监控--国产数据库通用模块开发

概述 Exporter是Prometheus监控系统中一个重要组件&#xff0c;可以理解为收集监控对象各种数据的agent。Prometheus为我们提供了较多的官方及第三方export&#xff0c;如果想要实现用户自己应用的监控&#xff0c;则需自己开发exporter,常用的监控对象大致可分为数据库对象&a…

ClickHouse--03--数据类型

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 数据类型1. Int2.FloattoFloat32(...) 用来将字符串转换成 Float32 类型的函数toFloat64(...) 用来将字符串转换成 Float64 类型的函数 3.DecimaltoDecimal32(value…

Linux常用make命令

一、简介 make 是一个常用的命令行工具&#xff0c;用于自动化构建和管理软件项目。它通常用于编译源代码、生成可执行文件或库&#xff0c;并处理项目中的依赖关系。 make 命令使用一个名为 “Makefile” 的文件来定义构建规则和目标。Makefile 中包含了一系列规则&#xff0…

视觉开发板—K210自学笔记(五)

本期我们来遵循其他单片机的学习路线开始去用板子上的按键控制点亮LED。那么第一步还是先知道K210里面的硬件电路是怎么连接的&#xff0c;需要查看第二节的文档&#xff0c;看看开发板原理图到底是按键是跟哪个IO连在一起。然后再建立输入按键和GPIO的映射就可以开始变成了。 …

Redis中缓存问题

缓存预热 Redis缓存预热是一项关键任务&#xff0c;可帮助提升应用程序的性能和响应速度。在高流量的应用程序中&#xff0c;Redis缓存预热可以加速数据查询和读取&#xff0c;从而改善用户体验。本文将介绍一种快速、稳定的Redis缓存预热方案&#xff0c;并提供相应代码实现。…