当前位置: 首页 > news >正文

ArrayList的自动扩容机制源码

Java的ArrayList的自动扩容机制


ArrayList是 Java 中极为常用的动态数组实现类,它依托数组存储数据,能依据实际需求灵活变动容量,高效管理元素集合。在深挖底层源码细节前,先来了解创建ArrayList集合并添加元素时的运作流程:

  • 默认初始化:空参构造时,ArrayList 使用一个长度为 0 的空数组,并不立即分配内存。
  • 首次添加:在首次添加元素时,数组容量初始化为 10。
  • 扩容机制:当数组满时,容量扩展为原来的 1.5 倍,以平衡性能与空间利用率。
  • 批量添加:使用 addAll() 方法时,容量直接扩展到满足新元素的实际需求,避免浪费。

成员变量

ArrayList 的核心成员变量如下:

private static final int DEFAULT_CAPACITY = 10; // 默认容量
private static final Object[] EMPTY_ELEMENTDATA = {}; // 空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 默认空数组
transient Object[] elementData; // 数据存储数组
private int size; // 当前元素数量
  • DEFAULT_CAPACITY:默认初始容量为 10。
  • EMPTY_ELEMENTDATADEFAULTCAPACITY_EMPTY_ELEMENTDATA:两种不同场景下的空数组,前者表示完全空的集合,后者表示初始化容量为空但可扩展的集合。
  • elementData:存放实际数据的数组。
  • size:记录当前数组中的元素个数。

构造方法

ArrayList 提供了三种构造方法,其中常用的是空参构造方法:

public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

工作机制

  • 空参构造方法并未立即分配内存,而是初始化一个长度为 0 的空数组 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
  • 真正分配内存发生在第一次添加元素时,数组容量会初始化为默认容量 10

add 方法

当我们调用 add 方法添加元素时,例如:

ArrayList<String> list = new ArrayList<>();
list.add("Hello");

以下是 add 方法的源码:

public boolean add(E e) {modCount++;add(e, elementData, size);return true;
}

该方法调用了重载方法 add(E e, Object[] elementData, int size)


重载 add 方法解析

private void add(E e, Object[] elementData, int s) {if (s == elementData.length) // 判断是否需要扩容elementData = grow();elementData[s] = e; // 将元素插入数组size = s + 1; // 更新 size
}

关键逻辑

  1. 扩容检查:如果当前数组已满(size == elementData.length),调用 grow 方法进行扩容。
  2. 新增元素:将元素插入数组的 size 位置,并将 size 自增 1。

grow 方法的扩容机制

扩容是动态数组的核心功能,其代码如下:

private Object[] grow() {return Arrays.copyOf(elementData, newCapacity(size));
}private int newCapacity(int minCapacity) {int oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容为原来的 1.5 倍return (newCapacity - minCapacity > 0) ? newCapacity : minCapacity;// 若实际长度更大,则扩容为实际长度
}

grow方法只完成了一件事,那就是将原本用来存放元素的数组拷贝到一个新的数组的当中完成扩容,新数组的长度为newCapacity(size)方法的返回值,也就是扩容后的长度
newCapacity(size)方法中传入了目前集合的长度size,并将其定义为了minCapacity,即最小容量,获取元素数组的长度定义为oldCapacity ,即旧容量大小,将旧的容量进行右移操作,使其大小变为原来的1/2,加上旧容量,定义为newCapacity ,即新容量的大小是旧容量大小的1.5倍,由此可见,默认的自动扩容机制扩容后的大小为原来的1.5倍,最后返回值为一个三元运算符,返回了较大的容量,也就是说1.5倍的容量满足不了当前的需求时,就会以实际的容量大小来进行扩容

逻辑详解

添加元素
数组已满吗
调用 grow 方法
计算新容量
1.5倍旧容量 >= 需要容量
使用 1.5倍旧容量
使用需要容量
复制数据到新数组
添加元素到数组
更新 size

相关文章:

ArrayList的自动扩容机制源码

Java的ArrayList的自动扩容机制 ArrayList是 Java 中极为常用的动态数组实现类&#xff0c;它依托数组存储数据&#xff0c;能依据实际需求灵活变动容量&#xff0c;高效管理元素集合。在深挖底层源码细节前&#xff0c;先来了解创建ArrayList集合并添加元素时的运作流程&#…...

【llm_inference】react框架(最小code实现)

ReAct&#xff1a;结合推理和行动的大语言模型推理架构 GitHub Code: 人人都能看懂的最小实现 引言 在人工智能领域&#xff0c;大语言模型&#xff08;LLM&#xff09;的应用日益广泛&#xff0c;但如何让模型能够像人类一样&#xff0c;在思考的基础上采取行动&#xff0c…...

PT8M2103 触控 I/O 型 8-Bit MCU

1 产品概述 ● PT8M2103 是一款可多次编程(MTP)I/O 型8位 MCU&#xff0c;其包括 2K*16bit MTP ROM、256*8bit SRAM、PWM、Touch 等功能&#xff0c;具有高性能精简指令集、低工作电压、低功耗特性且完全集成触控按键功能。为各种触控按键的应用&#xff0c;提供了一种简单而又…...

英语时态学习+名词副词形容词变形方式

开发出头不容易 不如跨界卷英语 英语中的16种时态是由四种时间&#xff08;现在、过去、将来、过去将来&#xff09;和四种体&#xff08;一般、进行、完成、完成进行&#xff09;组合而成的。以下是每种时态的详细说明和例句&#xff1a; 一般现在时 (Simple Present) 用法…...

浏览器解析页面流程

从输入一个url到页面解析完成的流程 1. 网络进程 1. 获取url 浏览器首先判断输入的url是否有http缓存&#xff0c;如果有则直接从http缓存中读取数据并显示。如果没有&#xff0c;则进行下一步。进行DNS解析&#xff0c;获取域名对应的IP地址。 2.下载html文件 浏览器根据I…...

图的遍历之DFS邻接矩阵法

本题要求实现一个函数&#xff0c;对给定的用邻接矩阵存储的无向无权图&#xff0c;以及一个顶点的编号v&#xff0c;打印以v为起点的一个深度优先搜索序列。 当搜索路径不唯一时&#xff0c;总是选取编号较小的邻接点。 本题保证输入的数据&#xff08;顶点数量、起点的编号等…...

Java --- JVM编译运行过程

目录 一.Java编译与执行流程&#xff1a; 二.编译过程&#xff1a; 1.编译器&#xff08;javac&#xff09;&#xff1a; 2.字节码文件&#xff08;.class&#xff09;&#xff1a; 三.执行过程&#xff1a; 1.启动JVM&#xff08;Java虚拟机&#xff09;&#xff1a; 2…...

HTML5 拖拽 API 深度解析

一、HTML5 拖拽 API 深度解析 1.1 背景与发展 HTML5 的拖拽 API 是为了解决传统拖拽操作复杂而设计的。传统方法依赖鼠标事件和复杂的逻辑计算&#xff0c;而 HTML5 提供了标准化的拖拽事件和数据传递机制&#xff0c;使得开发者能够快速实现从一个元素拖拽到另一个元素的交互…...

GO--基于令牌桶和漏桶的限流策略

至于为什么要限流&#xff0c;字面意思已经很清楚了&#xff0c;就是为了减轻服务器的压力 下面我们将介绍两个限流策略----漏桶和令牌桶。 漏桶 原理介绍 漏桶&#xff0c;顾名思义就是一个漏斗&#xff0c;漏斗嘴的大小是固定的&#xff0c;所以不管漏斗现容量多大&#…...

MongoDB性能监控工具

mongostat mongostat是MongoDB自带的监控工具&#xff0c;其可以提供数据库节点或者整个集群当前的状态视图。该功能的设计非常类似于Linux系统中的vmstat命令&#xff0c;可以呈现出实时的状态变化。不同的是&#xff0c;mongostat所监视的对象是数据库进程。mongostat常用于…...

Axure设计之模拟地图人员移动轨迹

在产品原型设计时&#xff0c;为了更好的表达和呈现预期的效果&#xff0c;让客户或开发看一眼就能理解要实现的功能&#xff0c;往往需要在产品设计时尽量去接近现实&#xff0c;这就需要我们在使用Axure制作原型时应具有高度细节和逼真度的原型设计。原型设计不仅包含了产品的…...

Android环境搭建

Android环境搭建 第一步&#xff1a;安装 Homebrew 执行以下命令来安装 Homebrew&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"检测是否安装成功&#xff1a; brew --version第二步&#xff1a;安装 No…...

前端工程化面试题(一)

如何使用 Docker 部署前端项目&#xff1f; 使用 Docker 部署前端项目通常涉及以下几个步骤&#xff1a; 创建项目&#xff1a;首先&#xff0c;需要在本地创建并配置好前端项目。 准备 Docker 文件&#xff1a; .dockerignore&#xff1a;这个文件用于排除不需要上传到 Dock…...

模型案例:| 手机识别模型!

导读 2023年以ChatGPT为代表的大语言模型横空出世&#xff0c;它的出现标志着自然语言处理领域取得了重大突破。它在文本生成、对话系统和语言理解等方面展现出了强大的能力&#xff0c;为人工智能技术的发展开辟了新的可能性。同时&#xff0c;人工智能技术正在进入各种应用领…...

期权懂|个股期权交割操作流程是什么样的?

期权小懂每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 个股期权交割操作流程是什么样的&#xff1f; 一、行权申报&#xff1a; 期权买方在行权日通过其经纪商提交行权指令&#xff0c;表明其决定行使期权权利。 二、行权匹配&#xf…...

【openGauss】openGauss execute执行update语句,获取更新的行数

【openGauss】openGauss execute执行update语句&#xff0c;获取更新的行数 在openGauss中&#xff0c;可以使用execute语句执行update语句&#xff0c;并通过GET DIAGNOSTICS语句获取更新的行数。下面是一个示例&#xff1a; DO $$ DECLAREupdated_rows INTEGER; BEGINEXECUT…...

P8780 [蓝桥杯 2022 省 B] 刷题统计

题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 &#x1d44e;道题目&#xff0c;周六和周日每天做 &#x1d44f; 道题目。请你帮小明计算&#xff0c;按照计划他将在第几天实现做题数大于等于 &#x1d45b; 题? 输入格式 输入一行包含三…...

切比雪夫不等式:方差约束下的概率估计

切比雪夫不等式&#xff1a;方差约束下的概率估计 背景 在概率分析中&#xff0c;切比雪夫不等式是一个常用的工具&#xff0c;它通过引入随机变量的 方差信息&#xff0c;给出了偏离均值的概率界限。这一不等式是对 马尔科夫不等式 的自然扩展&#xff0c;结合了更丰富的分布…...

使用CancellationTokenSource来控制长时间sql查询中断

前端 <!-- 透明的覆盖层&#xff0c;显示在页面上方&#xff0c;包含进度条 --><Grid Visibility"{Binding IsLoading}" Background"Transparent" HorizontalAlignment"Stretch" VerticalAlignment"Stretch" ZIndex"1&…...

小红薯最新x-s 算法补环境教程12-06更新(下)

在上一篇文章中已经讲了如何去定位x-s生成的位置&#xff0c;本篇文章就直接开始撸代码吧 如果没看过的话可以看&#xff1a;小红薯最新x-s算法分析12-06&#xff08;x-s 56&#xff09;&#xff08;上&#xff09;-CSDN博客 1、获取加密块代码 首先来到参数生成的位置&…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...