ArrayList扩容机制

2023-11-06

    • 扩容步骤

  1. 扩容:把原来的数组复制到另一个内存空间更大的数组中。

  1. 添加元素:把新元素添加到扩容以后的数组中。

2、源码分析

2.1 ArrayList里面的属性

    /**
     * 默认初始化容量.
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * 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.
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * ArrayList的大小 (它包含的元素个数).
     *
     * @serial
     */
    private int size;

2.2 构造方法

分析之前我们先看一下ArrayList的两个构造方法

  • ArrayList():在用无参构造来创建对象的时候其实就是创建了一个空数组,长度为0。

  • ArrayList(int initialCapacity):传入的参数是正整数就按照传入的参数来确定创建数组的大小,否则异常。

    /**
     * Constructs an empty list with the specified initial capacity.
     *
     * @param  initialCapacity  the initial capacity of the list
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

2.3 扩容

add方法就两步,

  1. 第一步:增加长度。

  1. 第二步:添加元素到数组,第二步就是将数据放到新数组最后一位。

第二步没什么好讲的,下面主要讲第一步。

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        // 增加长度
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 添加元素
        elementData[size++] = e;
        return true;
    }

我们看看ensureCapacityInternal(int minCapacity)这个增加长度的方法

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

这个地方我们看到了,如果在添加的时候远数组是空的,就直接给一个10的长度,否则的话就是size+1。

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    if (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 code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (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);
}

扩容实现:

  • int newCapacity = oldCapacity + (oldCapacity >> 1);表示新容量=旧容量+0.5*旧容量=1.5倍旧容量。

  • elementData = Arrays.copyOf(elementData, newCapacity);将旧数组数据复制到新数组。

扩容结束。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ArrayList扩容机制 的相关文章

  • 如何克服原语按值传递的事实

    我有一段很长的代码来计算两个值 doubles 对我来说 我在几个地方使用了这段代码 为了坚持 DRY 原则 我应该将这段代码重构为一个很好的单元测试方法 但是我不能让它返回两个双精度数 而双精度数是原始的 因此不能按值传递和操作 我能想到
  • 在文本文件中写入多行(java)

    下面的代码是运行命令cmd并使用命令行的输出生成一个文本文件 下面的代码在 Eclipse 的输出窗口中显示了正确的信息 但在文本文件中只打印了最后一行 谁能帮我这个 import java io public class TextFile
  • 使用 JPA Criteria API 进行分页的总行数

    我正在系统中为实体实现 高级搜索 功能 以便用户可以使用该实体的属性上的多个条件 eq ne gt lt 等 来搜索该实体 我正在使用 JPA 的 Criteria API 动态生成 Criteria 查询 然后使用setFirstResu
  • org.apache.sling.api.resource,version=[2.3,3) -- 无法解析

    您好 我无法访问我的项目内容 我已经上传了从 CQ 访问内容所需的所有包 我唯一能看到的是 org apache sling api resource version 2 3 3 无法解析 这是否是异常的原因 如果是 请告诉我如何解决 中Q
  • OSGi:如果不取消服务会发生什么

    这是我获取 OSGi 服务的方式 ServiceReference reference bundleContext getServiceReference Foo class getName Foo foo Foo bundleContex
  • java中如何连接字符串

    这是我的字符串连接代码 StringSecret java public class StringSecret public static void main String args String s new String abc s co
  • Cassandra java驱动程序协议版本和连接限制不匹配

    我使用的java驱动程序版本 2 1 4卡桑德拉版本 dsc cassandra 2 1 10cql 的输出给出以下内容 cqlsh 5 0 1 Cassandra 2 1 10 CQL spec 3 2 1 Native protocol
  • 当从服务类中调用时,Spring @Transactional 不适用于带注释的方法

    在下面的代码中 当方法内部 是从内部调用的方法外部 应该在交易范围内 但事实并非如此 但当方法内部 直接从调用我的控制器class 它受到事务的约束 有什么解释吗 这是控制器类 Controller public class MyContr
  • 在 S3 中迭代对象时出现“ConnectionPoolTimeoutException”

    我已经使用 aws java API 一段时间了 没有遇到太多问题 目前我使用的是库 1 5 2 版本 当我使用以下代码迭代文件夹内的对象时 AmazonS3 s3 new AmazonS3Client new PropertiesCred
  • 画透明圆,外面填充

    我有一个地图视图 我想在其上画一个圆圈以聚焦于给定区域 但我希望圆圈倒转 也就是说 圆的内部不是被填充 而是透明的 其他所有部分都被填充 请参阅这张图片了解我的意思 http i imgur com zxIMZ png 上半部分显示了我可以
  • 匿名类上的 NotSerializedException

    我有一个用于过滤项目的界面 public interface KeyValFilter extends Serializable public static final long serialVersionUID 7069537470113
  • Java 8 流 - 合并共享相同 ID 的对象集合

    我有一系列发票 class Invoice int month BigDecimal amount 我想合并这些发票 这样我每个月都会收到一张发票 金额是本月发票金额的总和 例如 invoice 1 month 1 amount 1000
  • IntelliJ - 调试模式 - 在程序内存中搜索文本

    我正在与无证的第三方库合作 我知道有一定的String存储在库深处的某个字段中的某处 我可以预测的动态值 但我想从库的 API 中获取它 有没有一种方法可以通过以下方式进行搜索 类似于全文搜索 full程序内存处于调试模式并在某个断点处停止
  • Struts 2 + Sitemesh 3 集成 - FreemarkerDecoratorServlet 中的 NPE

    我将 Struts 2 版本 2 3 14 3 与 Sitemesh 3 版本 3 0 alpha 2 一起使用 并且在某些情况下遇到 NullPointerException 首先 这是我的 web xml 中的 struts2 site
  • Java中的Object类是什么?

    什么是或什么类型private Object obj Object http download oracle com javase 6 docs api java lang Object html是Java继承层次结构中每个类的最终祖先 从
  • FileOutputStream.close() 中的设备 ioctl 不合适

    我有一些代码可以使用以下命令将一些首选项保存到文件中FileOutputStream 这是我已经写了一千遍的标准代码 FileOutputStream out new FileOutputStream file try BufferedOu
  • Trie 数据结构 - Java [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 是否有任何库或文档 链接提供了在 java 中实现 Trie 数据结构的更多信息 任何帮助都会很棒 Thanks 你可以阅读Java特里树
  • 如何从 Maven 存储库引用本机 DLL?

    如果 JAR 附带 Maven 存储库中的本机 DLL 我需要在 pom xml 中放入什么才能将该 DLL 放入打包中 更具体地举个例子Jacob http search maven org artifactdetails 7Cnet s
  • 带有 Maven Wrapper 的 Java 17 导致无法识别的 VM 选项“MaxPermSize=512m”

    I use OpenJDK 17 https jdk java net 17 使用 Maven Wrapper 3 8 2 从春季初始化 https start spring io Maven项目 JAR打包 Java 17 Spring
  • 如何在 JFreeChart 中设置多个系列的线条粗细?

    我创建了很多图表 在他们每个人中我都需要打电话 renderer setSeriesStroke i new BasicStroke 2 0f 对于每个系列 renderer is chart getXYPlot getRenderer 我

随机推荐

  • 滑动拼图和文字点选两种类型的验证码

    前言 行为验证码通过用户的操作来完成验证 常见的行为验证码有拖动式和点触式 拖动式验证就是根据图片显示 将指定的图形拖动到指定位置完成验证 而点触式验证码就是通过鼠标点击出示例中出现的图形完成验证 行为验证码应用 今天推荐一款非常优秀的行为
  • DOM操作-上移下移

    HTML ul li span 啦啦啦啦 span i 1 i li ul
  • anaconda prompt 常用命令

    1 查看已安装的包 conda list 2 更新所有包 conda upgrade all 3 安装包 conda install package name 4 删除包 conda remove package name 5 更新包 co
  • 以太坊学习

    ubuntu 安装go 自行百度 下载ethererum客户端 github 将ethererum 解压放在GOPATH下 进入 ethererum文件夹 执行 make geth 或者make all 可能会报错 原因 所下载的库依赖有官
  • java中的数据类型转换,常量类型

    文章目录 一 隐式转换 二 强制转换 三 java中常量优化机制 四 常量类型 一 隐式转换 所谓隐式转换 就是将数据类型中 取值范围小的数据 给取值范围大的类型数据赋值 可以直接赋值 首先 看一段代码 int a 10 double b
  • IMAGE INPAINTING

    IMAGE INPAINTING We need get good Int i j I t n i j Here using Laplacian Operator http www cnblogs com xfzhang archive 2
  • Java中访问控制符

    说明 Java中提供了四种访问控制符 分别是private default protected和public 其访问控制级别从小到大如图所示 1 private 当前类访问权限 用private修饰的变量或方法只能被该类自身所访问和修改 而
  • 虚拟机自动重启问题

    性能测试一般要运行好几天不能关机的 万一遇到系统重启之前跑的可能都前功尽弃了 真的是很头疼的 同样 如果是运行中的项目服务遇到这种情况给用户的使用感受也是特别差的 所以 我会修改系统的自动重新启动设置 Windows Server自动重启的
  • tomcat默认端口号(三个tomcat端口号)

    tomcat默认端口号 三个tomcat端口号 2020 05 08 10 43 21 共10个回答 Tomcat的默认端口号是多少 您好 提问者 Tomcat的默认端口号是 8080 weblogic的默认端口号是 7001 tomcat
  • MSP430学习笔记-架构篇

    最近开始接触MSP430单片机了 打算先把手册结合着书看一遍 之后用来做一个小玩意儿 学习笔记就按照学习进度来更新吧 也算做个备忘 有什么东西不记得了可以来翻一翻 今天我们来聊聊MSP430架构 一 MSP430简介 MSP430是由德州仪
  • [Intel汇编-NASM]进入保护模式全过程

    enter pm mbr org 0x7C00 该命令表示程序将被装在到偏移地址为0x7C00的地方 该命令效果是全局的 但只能使用一次 之后不得再用 从该位置开始到整个源代码结束之间的所有标号在被访问时都会隐式地自动加上0x7C00 但是
  • MicroPython1.19.1添加C模块

    1 样例路径 官方添加C模块例子在 micropython 1 19 1 examples usercmodule路径中 2 编译 make USER C MODULES examples usercmodule BOARD MY STM3
  • 3D游戏建模怎么接外包

    3D游戏建模怎么接外包 有些自学出来或者经过培训小伙伴 已经有能力做出作品时往往都想着怎么去赚钱 除了从事于建模行业的工作之余 身为大学生 可能在校的时间较为富裕 课余时间 能够接私单 赚点外快什么的也是能够的 接单的平台 八戒网 1个较为
  • 大学生必看的电影

    十大励志电影 1 肖申克的救赎 很喜欢安迪放MOZART的 费加罗的婚礼 那段 圣洁高亢的女高音穿云裂帛久被牢 牢禁锢的人们呆住了 他们可能不知这是什么音乐 可是对美的感觉 对自由的渴望 每个人都是一样 人们抬头望着碧蓝无垠的天空 美好的情
  • 网络--HTTP协议

    网络基础知识之 HTTP 协议 首先让我们从一个问题入手 当我们在浏览器中输入 http www baidu com 访问百度的时候浏览器做了哪些事情 这里以 Chrome 浏览器为例 1 DNS域名解析 首先 Chrome 搜索自身的 D
  • 针对某个逻辑卷进行fscheck修复文件系统

    系统启动无法正常启动 原因为 dev vg telstar telstar 该逻辑卷无法加载 报contains a file system with errors check forced OK那就根据该提示进行该逻辑卷的检查恢复工作 注
  • 多态的实现

    1 理解如何通过virtual fuction table指向正确的方法 Typically the compiler creates a separate vtable for each class When an object is c
  • 八大排序(一)冒泡排序,选择排序,插入排序,希尔排序

    一 冒泡排序 冒泡排序的原理是 从左到右 相邻元素进行比较 每次比较一轮 就会找到序列中最大的一个或最小的一个 这个数就会从序列的最右边冒出来 以从小到大排序为例 第一轮比较后 所有数中最大的那个数就会浮到最右边 第二轮比较后 所有数中第二
  • 后端跨域问题解决

    出于浏览器的同源策略限制 同源策略 Sameoriginpolicy 是一种约定 它是浏览器最核心也最基本的安全功能 如果缺少了同源策略 则浏览器的正常功能可能都会受到影响 可以说Web是构建在同源策略基础之上的 浏览器只是针对同源策略的一
  • ArrayList扩容机制

    扩容步骤 扩容 把原来的数组复制到另一个内存空间更大的数组中 添加元素 把新元素添加到扩容以后的数组中 2 源码分析 2 1 ArrayList里面的属性 默认初始化容量 private static final int DEFAULT C