当前位置: 首页 > 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、获取加密块代码 首先来到参数生成的位置&…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...