ArrayList扩容机制

简介: ArrayList 添加元素时,先调用 `ensureCapacityInternal` 检查容量,首次添加时默认扩容至 10。`grow()` 方法实现扩容,新容量为旧容量的 1.5 倍(通过位运算 `>>` 提升效率),确保数组动态扩展性能。`length` 用于数组长度,`length()` 是字符串方法,`size()` 用于集合元素计数。

● 先来看Add方法
/* 将指定的元素追加到此列表的末尾
*/
public boolean add(E e) {
//添加元素之前,先调用ensureCapacityInternal方法
ensureCapacityInternal(size + 1); // Increments modCount!!(增量modCount)
//这里看到ArrayList添加元素的实质就相当于为数组赋值
elementData[size++] = e;
return true;
}
● 再来看看ensureCapacityInternal()方法,可以看到add()方法首先调用了ensureCapacityInternal(size+1)
//得到最小扩容量
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//获取默认的容量和传入参数的较大值(第一次的较大值是DEFAULT_CAPACITY=10,minCapacity=1)
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
当要add进第一个元素时,minCapacity为1,在Math.max()方法比较后,minCapacity为10
● ensureExplicitCapacity()方法
//判断是否需要扩容
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//调用grow()方法进行扩容,调用此方法代表已经开始扩容了
grow(minCapacity);
}
我们来仔细分析一下

  1. 当我们要add进第一个元素到ArrayList时,elementData.length为0(因为还是一个空的list,里面还没有数据,所以没有进行扩容,默认扩容10),因为执行了ensureCapacityInternal()方法,所以minCapacity此时为10。此时,minCapacity - elemetData.length > 0(minCapacity=10,elemetData.length=0)成立,所以会进入==grow(minCapacity)==方法。
  2. 当add第2个元素时,minCapacity为2,此时elementData.length(容量)在添加第一个元素后扩容成10了。此时,minCapacity - elementData.length > 0不成立,所以不会进入(执行)==grow(minCapacity)==方法。
  3. 添加第3、4…到第10个元素时,依然不会执行==grow()==方法,数组容量都为10。
    知道添加第11个元素,minCapacity(为11)比elementData.length(为10)要大。进行grow方法进行扩容
  4. grow方法
    private void grow(int minCapacity) {
    // oldCapacity为旧容量,newCapacity为新容量
    int oldCapacity = elementData.length;//(0,10,15)
    //将oldCapacity右移一位,其效果相当于oldCapacity/2;
    // 我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么久把最小需要容量当作数组的新容量
    if (newCapacity - minCapacity < 0)
     newCapacity = minCapacity;
    
    //判断新容量是否大于集合的最大容量(一般大不了)
    if (newCapacity - MAX_ARRAY_SIZE > 0)
     newCapacity = hugeCapacity(minCapacity);
    
    // 给elementData从新赋值(10,15)
    elementData = Arrays.copyOf(elementData, newCapacity);
    }
    int newCapacity = oldCapacity + (oldCapacity >> 1),所以 ArrayList 每次扩容之后容量都会变为原来的 1.5 倍!
    “>>”(移位运算符):>>1 右移一位相当于除2,右移n位相当于除以 2 的 n 次方。这里 oldCapacity 明显右移了1位所以相当于oldCapacity /2。对于大数据的2进制运算,位移运算符比那些普通运算符的运算要快很多,因为程序仅仅移动一下而已,不去计算,这样提高了效率,节省了资源
    通过例子探究一下grow()方法
    ● 当add第一个元素时,oldCapacity为0,经比较后第一个if判断成立,newCapacity = minCapacity(为10)。但是第二个if判断不会成立,即newCapacity不比MAX_ARRAY_SIZE大,则不会进入hugeCapacity方法。数组容量为10,add方法中return true,size增为1。
    ● 当add第11个元素进入grow方法时,newCapacity为15,比minCapacity(为11)大,第一个if判断不成立。新容量没有大于数组最大size,不会进入hugeCapacity方法。数组容量扩为15,add方法中rerurn,true,size增为11。
    ● 以此类推…
    这里补充一点比较重要,但是容易被忽视掉的知识点:
    ● java中的length属性是针对数组说的,比如说你声明了一个数组,想知道这个数组的长度则用到了length这个属性。
    ● java中的length() 方法是针对字符串说的,如果想看这个字符串的长度则用到 length() 这个方法。
    ● java中的size() 方法是针对泛型集合说的,如果想看这个泛型有多少元素,就调用此方法类查看!
相关文章
|
人工智能 算法 前端开发
我和通义灵码的一周年
通义灵码是阿里巴巴推出的一款AI插件,大小约5.8M,适用于IDEA开发环境。它通过@workspace和@terminal两大功能,显著提升代码开发效率和质量。@workspace帮助开发者快速理解项目结构,智能导航至关键代码;@terminal则提供命令行下的代码搜索与实时补全,加速开发流程。实际应用中,通义灵码大幅缩短了新项目熟悉时间,减少了试错成本,提升了代码的规范性和稳定性。
640 0
|
7月前
|
SQL 关系型数据库 MySQL
Quick BI使用案例16:利用“SQL预聚合+图表二次汇总”实现最大值求和
本文详解如何通过自定义SQL预聚合结合仪表板二次汇总(列小计求和),突破SUM(MAX())嵌套限制,实现“各区域各类运输方式最大订单额求和”,助力识别高价值客户与优化高端物流策略。
|
6月前
|
弹性计算 人工智能 缓存
阿里云新用户、老用户活动集锦,新购、续费云服务器最新优惠政策与活动
2026年,阿里云为新老用户打造了极具吸引力的优惠政策体系。新用户可享38元轻量服务器抢购、u2i实例3折起等优惠,新用户还有专属折扣券、特定产品特价等权益。对于老用户,阿里云提供“长效特惠”模式,如99元/199元实例新购续费同价,解决“续费贵”问题,同时常规续费也有折扣。用户应厘清身份、把握首购特惠、关注续费与升级、善用优惠组合,以最优成本获取稳定可靠的云服务器资源。
|
12月前
|
存储 弹性计算 人工智能
阿里云渠道商:云文件存储 NAS是什么?
阿里云NAS提供云端共享存储,多台服务器可同时访问同一文件,解决版本混乱难题。支持跨地域挂载、自动备份与按需付费,适用于团队协作、数据共享等场景,开箱即用,免运维,助力企业高效上云。
|
10月前
|
前端开发 Java API
吃透 Spring 体系结构
本文深入剖析Spring框架的体系结构,围绕IOC(控制反转)和AOP(面向切面编程)两大核心思想,系统讲解了核心容器、AOP、数据访问与Web模块的原理及实战应用,并辨析了常见技术点差异,助力开发者掌握其设计精髓。
387 2
|
10月前
|
jenkins 持续交付 调度
项目《神领物流》
本项目为自研物流系统,基于微服务架构实现智能调度与管控,涵盖用户、快递员、司机多端应用。采用GitFlow管理代码,通过Jenkins实现持续集成,提交后自动构建,保障开发效率与系统稳定,类似顺丰速运模式,面向C端提供高效快递服务。(239字)
|
10月前
|
设计模式 Java 程序员
推荐书籍
推荐多本Java经典书籍:《Head First Java》适合入门,《Java核心技术》深入巩固基础,《Java编程思想》整合设计模式,适合进阶。并发方面有《Java并发编程之美》等,JVM推荐《深入理解Java虚拟机》与《实战JVM》。体系全面,适合不同阶段学习。
|
10月前
|
负载均衡 算法 Java
微服务篇
SpringBoot核心原理是自动装配,通过@SpringBootApplication注解实现配置类、组件扫描与自动配置。其启动流程包括环境初始化、上下文创建与自动化配置。常用起步依赖如web、redis等;支持properties、YAML等配置文件,后加载的覆盖先加载的。项目通过Feign、Ribbon实现服务通信与负载均衡,使用Nacos做注册与配置中心,Sentinel或Hystrix实现限流熔断,Gateway实现网关限流与CORS跨域控制,结合Spring Cloud五大组件构建微服务架构。
|
10月前
|
缓存 开发工具 git
QLExpress使用及源码分析
QLExpress是阿里开源的轻量级规则引擎,支持通过注解与YAML配置实现业务逻辑与代码解耦。结合实体别名、接口规则定义及脚本化表达式,实现动态计算与判断,如用户年龄判断、BMI计算等。支持AST语法树解析与上下文绑定,提供灵活的二次扩展能力,适用于复杂业务场景的延迟执行与缓存优化。

热门文章

最新文章