聊一聊jdk1.8中的ArrayList 底层数组是如何扩容的

ArrayList 是一种常用的动态数组数据结构,底层依托于一个 Object[] 数组,当数组已满或者添加元素个数达到预分配的容量时,需要对数组进行扩容以继续添加元素。在 JDK1.8 中,时常听到关于 ArrayList 扩容的问题,接下来我将详细介绍 ArrayList 的底层数组如何扩容。

ArrayList 底层数组的定义

在 JDK1.8 的 ArrayList 中,底层数组的定义如下:

transient Object[] elementData; // 非私有的、仅在类 ArrayList 内部使用的数组,用于存储添加的元素。

其中,transient 关键字表示该字段不会被序列化。

ArrayList 底层数组扩容机制

ArrayList 中通过 ensureCapacityInternal 方法来判断是否需要对底层数组进行扩容,具体流程如下:

  1. 首先判断是否需要扩容。
private void ensureCapacityInternal(int minCapacity) {
        // 如果底层数组为空,则分配一个默认容量的数组
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        // 如果需要的最小容量大于现有数组容量,则需要扩容
        ensureExplicitCapacity(minCapacity);
}
  1. 调用 ensureExplicitCapacity 方法扩容。
private void ensureExplicitCapacity(int minCapacity) {
        // 修改扩容标志位
        modCount++;
        // 扩容时实际需要的最小容量为目前容量和需要的最小容量中的较大者
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
}

  1. grow 方法中,根据不同的情况进行扩容。
private void grow(int minCapacity) {
        // 获取此时底层数组的长度
        int oldCapacity = elementData.length;

        // 新容量为原来的1.5倍,向上取整
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;

        // 将底层数组复制到新的扩容底层数组中
        elementData = Arrays.copyOf(elementData, newCapacity);
}

扩容时,ArrayList 将底层数组的新容量计算为原来容量的1.5倍。同时,若所需的最小容量大于计算出的容量,则以所需容量为准。最后,通过调用 Arrays.copyOf 方法将原来的数组元素全部复制到新数组中去。

示例说明

示例一

下面是一段示例代码,演示 ArrayList 的扩容机制。

ArrayList<Integer> list = new ArrayList<>();

// 添加21个元素
for (int i = 1; i < 22; i++) {
  list.add(i);
}

System.out.println("当前数组容量:" + list.size());

输出结果如下:

当前数组容量:21

从结果可以看出,当添加元素个数达到数组容量的上限时,ArrayList 自动对底层数组进行扩容。

示例二

在一些场景下,我们需要对 ArrayList 进行优化,比如初始化时指定 ArrayList 的容量大小。下面是一段这样的示例代码:

ArrayList<Integer> list = new ArrayList<>(100);

// 添加100个元素
for (int i = 1; i < 101; i++) {
  list.add(i);
}

System.out.println("当前数组容量:" + list.size());

输出结果如下:

当前数组容量:100

从结果可以看出,当初始化时指定 ArrayList 的容量大小时,不需要进行数组扩容,大大提高了 ArrayList 的效率。

总结

ArrayList 底层数组的扩容机制是 ArrayList 实现动态数组的关键。扩容时,通过一定规则计算新的容量大小,并将原始数组复制到新的底层数组中,以完成实现动态数组的功能。在实际应用中,如有需要,可以根据不同情况对 ArrayList 进行一定程度的优化,以提高应用效率。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:聊一聊jdk1.8中的ArrayList 底层数组是如何扩容的 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • JDK动态代理过程原理及手写实现详解

    “JDK动态代理过程原理及手写实现详解”是一篇介绍Java JDK动态代理相关原理和手写实现方式的文章。下面我将详细讲解该攻略的内容和示例。 原理介绍 Java JDK动态代理是一种在运行时动态生成代理类的技术。它通过接口动态地生成代理类来实现对实际对象方法的代理。在运行时,JDK会根据要代理的接口生成一个实现该接口的代理类,并在方法执行前后执行一些额外的逻…

    Java 2023年5月26日
    00
  • java基础知识I/O流使用详解

    Java基础知识I/O流使用详解 1. I/O流概述 Java I/O流用于处理与设备(如磁盘、屏幕、键盘等)的输入和输出。在Java中,I/O流分为两个类型:字节流和字符流。字节流用于以字节为单位读取和写入数据,而字符流用于以字符为单位读取和写入数据。 I/O流被划分为四个抽象类:InputStream、OutputStream、Reader和Writer…

    Java 2023年5月24日
    00
  • Java之Arrays的各种功能和用法总结

    Java之Arrays的各种功能和用法总结 简介 Java中的Arrays类提供了一组用于操作数组的静态方法。Arrays类中的方法支持对数组的排序、搜索、比较、填充和转换等操作,该类还提供了一个asList()方法来创建一个ArrayList. 方法列表 下面是Arrays类中一些常用方法的列表: 方法 描述 sort() 对数组进行排序。 binaryS…

    Java 2023年5月26日
    00
  • SpringBoot DataSource数据源实现自动配置流程详解

    这里是关于SpringBoot DataSource数据源实现自动配置流程的详细攻略: 1. SpringBoot DataSource数据源的概述 SpringBoot 数据源(DataSource)是一个非常重要的组件,它是应用程序和后端数据库之间的桥梁。DataSource 有两个关键任务:一是管理数据库连接池,以便应用可以快速、高效地访问数据库;二是…

    Java 2023年6月2日
    00
  • SpringMVC结构简介及常用注解汇总

    以下是关于“SpringMVC结构简介及常用注解汇总”的完整攻略,其中包含两个示例。 SpringMVC结构简介 SpringMVC是一个基于MVC架构的Web框架,它提供了一种灵活、高效的方式来开发Web应用程序。在SpringMVC中,请求的处理流程可以分为以下几个步: 客户端发送请求到DispatcherServlet。 DispatcherServl…

    Java 2023年5月16日
    00
  • java组件smartupload实现上传文件功能

    下面是关于“java组件smartupload实现上传文件功能”的完整攻略,包含两个示例。 SmartUpload 简介 SmartUpload 是一个 Java 组件,能够方便地实现上传文件的功能。它提供了上传文件的基本方法,并可以使用 Java 类库自身的方法来读取这些文件。SmartUpload 支持批量上传,支持上传时的文件类型检查等功能。 Smar…

    Java 2023年5月19日
    00
  • Java String类正则操作示例

    Java String类正则操作示例 简介 Java中String类提供了很多方法进行正则表达式的操作。通过使用正则表达式,我们可以在字符串中匹配特定的字符或者模式,进行替换或者搜索等操作。在这篇文章中,我们将学习String类操作正则表达式的方法,并且提供两个实际的示例说明。 String类操作正则表达式的方法 Java String类提供了以下方法来操作…

    Java 2023年5月27日
    00
  • 浅谈servlet中的request与response

    关于“浅谈servlet中的request与response”,下面我来详细讲解一下。 什么是servlet中的request和response 在servlet中,request和response是指HTTP请求和响应中的对象,是Servlet API的一部分。这两个对象扮演了重要的角色,它们是处理HTTP请求和生成HTTP响应的必经之路。 具体而言,re…

    Java 2023年6月16日
    00
合作推广
合作推广
分享本页
返回顶部