Java 集合中 ArrayList 的扩容机制原理(面试+读源码)

           在 Java 中,ArrayList 内部是通过一个数组来存储元素的,是一个数组结构的存储容器。当向一个 ArrayList 中添加元素时,如果当前数组已经满了,就需要扩容。 

       

集合的继承关系图 

一、面试回答

( ArrayList 的扩容机制原理 ) 

        面试官好,ArrayList 是一个数组结构的存储容器,默认情况下,设置数组长度是 10. 当然我们也可以在构建 ArrayList 对象的时候自己指定初始长度。 随着在程序里面不断的往 ArrayList 中添加数据,当添加的数据达到 10 个的时候, ArrayList 就没有多余容量可以存储后续的数据。 这个时候 ArrayList 会自动触发扩容。 扩容的具体流程很简单, 1. 首先,创建一个新的数组,这个新数组的长度是原来数组长度的 1.5 倍。 2. 然后使用 Arrays.copyOf 方法把老数组里面的数据拷贝到新的数组里面。 扩容完成后再把当前要添加的元素加入到新的数组里面,从而完成动态扩容的过程。 以上就是我对这个我对这个问题的理解! 

或者不直接问: ArrayList 扩容是在第10个元素还是第11个元素触发的 ?

        在 Java 中,ArrayList 的扩容是在添加第11个元素时触发的,当 ArrayList 中的元素数量达到了其初始容量(默认为 10)时,ArrayList 会自动扩容,新的容量为原来的 1.5 倍。当然也可以在创建 ArrayList 对象时指定其初始容量,以避免频繁的扩容操作。

二、源码理解(Debug模式)

import java.util.ArrayList;
@SuppressWarnings({"all"})
public class ArrayListSource {

    public static void main(String[] args) {

        //解读源码
        //注意,注意,注意,Idea 默认情况下,Debug 显示的数据是简化后的,如果希望看到完整的数据
        //需要做设置. //使用无参构造器创建 ArrayList 对象
        ArrayList list = new ArrayList();
//        ArrayList list = new ArrayList(8);
        //使用 for 给 list 集合添加 1-10 数据
        for (int i = 1; i <= 10; i++) {
            list.add(i);
        }
        //使用 for 给 list 集合添加 11-15 数据
        for (int i = 11; i <= 15; i++) {
            list.add(i);
        }
        list.add(100);
        list.add(200);
        list.add(null);
    }
}
F7 单步调试进行下一步,遇到方法会进入方法内,同一行有多个方法时可以用左右键选择;
F8 单步调试,进行下一步,不会进入方法内;
Alt+Shift+F7强制进入方法内;
Shift+F8  直接跳出方法;
F9跳到下一个断点或者直接执行完程序

 

首先进入ArrayList的构造器,看到  elementData 第一次初始化的时候就是一个空数组

接下来进入到for循环,第一次进去会把int 给类型转化,进行一个装箱操作。 

 

然后在添加的时候 ,先执行了判断这个要添加的这个 e 的大小是否达到要求,满足了再将e放入

 

 第一次返回的一定是 10 (是规定好的了)

 

拿到 minCapacity 然后再进入到  ensureExplicitCapacity 其中modCount 表示被修改的次数(这里主要防止有多个线程同时去修改,如果有,则会抛出异常)

 

只有当  elementData 的大小小于10的时候就调用grow 方法进行扩容。

 

 先把传进来的数组大小赋值给一个变量 oldCapacity ,然后按照原先数组的1.5倍进行扩容(右移一位,相当于除以2) 而 Arrays.copyOf 其实就是数组的复制。

即得到了 10个 elementData 的空元素

 

ArrayList 的扩容机制是在添加元素时判断当前数组大小是否已经满了,如果已经满了,则创建一个新的更大的数组,并将原来的元素全部复制到新的数组中。具体的扩容规则如下:

  1. 当添加元素后,size 大小已经等于或超过了数组的容量 capacity 时,就会触发扩容操作。
  2. 扩容的大小默认情况下为原数组大小的一半。比如原数组大小为 10,那么扩容后的数组大小为 15。
  3. 如果扩容后的大小还是不够,那么就以添加元素的数量作为扩容大小,即新数组的大小为 oldCapacity + (oldCapacity >> 1) + 1。

        需要注意的是,ArrayList 中的数组无法动态地调整大小,因此每次扩容都需要创建新的数组和复制元素,这可能会带来一些性能损失。为了避免频繁扩容,我们可以在使用 ArrayList 时尽量预估元素数量,初始化时指定一个合适的初始容量。

在实际使用中,我们可以通过指定初始容量和适当的预估来优化扩容操作,以提高性能。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Solidity基础六

生活本来就是平凡琐碎的&#xff0c;哪有那么多惊天动地的大事&#xff0c;快乐的秘诀就是不管对大事小事都要保持热情 目录 一、Solidity的特殊变量(全局) 二、Solidity的不可变量 immutable的赋值方式 三、Solidity的事件与日志 事件和日志加深理解 四、Solidity的异常…

ChatGPT1论文解读《Improving Language Understanding by Generative Pre-Training》

论文总结 以下是我阅读完整篇论文做的个人总结&#xff0c;基本包含了chatGPT1设计的完整框架思路&#xff0c;可以仅看【论文总结】章节。 在GPT1实现的核心架构中&#xff0c;包含两个阶段。 第一阶段 在第一阶段基于一个包含7000本书籍内容的海量未标注文本数据集进行无…

注解-反射-XML配置原理

java刚开始原本是直接在方法中创建对象执行程序等&#xff0c;部分代码重复率高&#xff0c;后来就发展成方法封装调用&#xff0c;再后来出现的像spring框架等&#xff0c;引入了XML配置&#xff0c;使得程序更加简洁&#xff0c;方便等&#xff0c;其中XML配置也是基于java反…

java+iClientOpenlayers实现污水排放扩散模拟(湖库污染排放扩散模拟)

软件实现效果 一、应用背景 湖库污染是一个日益严峻的环境问题。随着城市化和工业化的加速发展&#xff0c;越来越多的有害物质被排放入湖库中&#xff0c;导致湖库污染加剧并扩散到周围地区。本文将探讨湖库污染扩散的原因、影响和解决方法。 首先&#xff0c;湖库污染扩散的…

堆排序之——TopK问题

思维导图&#xff1a; 一&#xff0c;TopK算法的运用 TopK的算法在我们的日常生活中可谓是大有用处&#xff0c;比如你在点外卖时外卖榜单上的销量前几名的筛选&#xff0c;富豪排行榜的榜单人物的筛选&#xff0c;游戏排位……等等领域都会有TopK算法的涉及。TopK问题的用处可…

github创建仓库和拉取代码

目录 一、git创建仓库 第一步&#xff1a;首先登录github 第二步&#xff1a;进入建立的仓库(或者新建仓库) 第三步&#xff1a;创建成功 第四步&#xff1a;在本地新建一个文件夹&#xff0c;然后在文件夹下打开git bash 第五步&#xff1a;在git bash命令框执行git init…

专业解读财务共享实现财务数智化转型的有效路径

近年来&#xff0c;随着数字经济的飞速发展&#xff0c;各大企业全面开启数智化转型之路&#xff0c;作为企业数智化转型的重要内容&#xff0c;财务数智化转型始于财务共享服务。然而&#xff0c;财务共享建设并不是一蹴而就的&#xff0c;如何通过财务共享实现财务数智化转型…

什么是分布式软件系统

:什么是分布式软件系统&#xff1f;分布式软件系统是什么意思&#xff1f; 分布式软件系统(Distributed Software Systems)是支持分布式处理的软件系统,是在由通信网络互联的多处理机体系结构上执行任务的系统。它包括分布式操作系统、分布式程序设计语言及其编译(解释)系统、分…

阻抗板是否高可靠,华秋有话说

随着高频高速电子产品的快速发展&#xff0c;信号传输过程更容易出现反射、串扰等信号完整性问题&#xff0c;且频率越高、传输速率越快&#xff0c;信号损耗越严重&#xff0c;如何降低信号在传输过程中的损耗、保证信号完整性是高频高速PCB发展中的巨大挑战。 在高速PCB设计…

Spring源码(一) — 序言

序言 Java程序员的日常开发一定都离不开Spring的框架&#xff0c;从Spring、SpringMVC、SpringBoot、SpringCloud… 而Spring框架就是Spring家族中最基础也是最重要的一个框架。 Spring 我们常说的Spring往往都绕不开IOC&#xff08;控制反转&#xff09;和AOP&#xff08;切…

【TellMeCode】使用VSCODE + ChatGPT辅助分析推测源码

【TellMeCode】使用VSCODE ChatGPT辅助分析推测源码 0x00 功能简介 根据代码上下文相关信息&#xff0c;如工作区文件夹名称&#xff0c;代码所在路径等一系列信息&#xff0c;提供给大模型更多元和尽可能多的信息&#xff0c;利用其自身优势去检索相关的文档和博客&#xf…

QT开发实战-动态壁纸软件

动态壁纸软件开发 项目源代码在下面链接获取: ----------------------------- 开发者:CodeSharkSJ 希望此项目能加强你对Qt的应用 文章目录 项目图与开发环境核心技术原理自定义窗口程序UI布局背景绘制样式表基本实现QWebEngineQMedia使用系统托盘隐藏记忆功能应用程序打包 …

RestCloud荣膺广东省优秀软件产品奖,引领国内数据集成领域!

近日&#xff0c;“2022年广东软件风云榜”名单公布&#xff0c;“谷云ETL数据交换软件”凭借其在助力企业数字化转型升级过程中的卓越表现&#xff0c;荣获由羊城晚报报业集团、广东软件行业协会、广东省大数据协会联合颁发的“优秀软件产品和解决方案”奖。 数字化转型是推动…

【P38】JMeter 随机控制器(Random Controller)

文章目录 一、随机控制器&#xff08;Random Controller&#xff09;参数说明二、测试计划设计2.1、测试计划一2.2、测试计划二2.3、勾选忽略子控制器块 一、随机控制器&#xff08;Random Controller&#xff09;参数说明 可以让控制器内部的逻辑随机执行一个&#xff0c;一般…

深度学习-第T8周——猫狗识别

深度学习-第T8周——猫狗识别 深度学习-第T8周——猫狗识别一、前言二、我的环境三、前期工作1、导入数据集2、查看图片数目 四、数据预处理1、 加载数据1.1、设置图片格式1.2、划分训练集1.3、划分验证集1.4、查看标签1.5、再次检查数据1.6、配置数据集 2、数据可视化 五、搭建…

机器学习常识 7: 决策树

摘要: 决策树是一种与人类思维一致, 可解释的模型. 1. 决策树的结构 人类的很多知识以决策规则的形式存储: 如果今天是阴天 (outlook overcast), 就去打球.如果今天出太阳 (outlook sunny) 而且湿度不高于 70% (humidity ≤ \le ≤ 70), 就去打球.如果今天出太阳 (outloo…

1688商品ID采集一件代发详情页面数据

本篇博文介绍了对1688商品详情API的二次封装&#xff0c;将URL参数封装成Python函数&#xff0c;直接传入参数即可获取搜索结果&#xff0c;例如1688商品标题、价格、一件代发、sku属性和URL等。提供了详细的代码示例和接口调用Demo。 1688.item_get-获得1688商品详情数据 1.请…

APP开发死亡潮来临 小程序是否会取而代之?

移动互联网的发展&#xff0c; APP开发行业也迎来了它的大时代。据有关数据显示&#xff0c;2017年上半年国内新增的 App数量达到了创纪录的449万款&#xff0c;用户使用时长超过了200亿分钟。移动互联网已成为名副其实的“流量”产业&#xff0c;也因此诞生出一大批 APP开发公…

Maven 概述及下载安装

一、为什么要学习 Maven 我们构建一个项目需要用到很多第三方的类库&#xff0c;就需要引入大量的jar包&#xff0c;并且Jar包之间的关系错综复杂&#xff0c;缺少任何一个Jar包都会导致项目编译失败。Maven 能帮助我们下载及管理依赖。 本地项目代码开发完成后&#xff0c;我…

类和对象【3】初始化列表

全文目录 引言初始化列表定义特性 总结 引言 上一篇文章中介绍了构造函数&#xff0c;它可以在实例化一个类对象的时候自动调用&#xff0c;以初始化类对象&#xff1a; 戳我看默认成员函数详解 但是&#xff0c;不难发现&#xff0c;在构造函数体中对成员变量的初始化其实是属…