Java ArrayList扩容机制原理深入分析

Java ArrayList扩容机制原理深入分析

在 Java 中,ArrayList 是一种动态数组,它可以自动扩容以适应数据的增长。了解 ArrayList 扩容机制的原理,有助于我们更好地理解和使用 ArrayList,提高代码效率。

ArrayList 扩容机制

ArrayList 内部使用数组来存储元素,当向 ArrayList 中添加元素时,如果当前数组已满,就需要扩容。下面是 ArrayList 扩容的基本流程:

  1. 获取当前 ArrayList 的容量 capacity 和当前 ArrayList 已存储的元素个数 size;
  2. 判断当前数组是否已满,即 size == capacity
  3. 如果数组已满,创建一个新的容量是原来容量 1.5 倍的数组,并将原数组中的元素复制到新数组中;
  4. 新数组成为 ArrayList 的内部数组。

下面是一个简单的示例:

import java.util.ArrayList;

public class Demo {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>(3);
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
    }
}

在上面的例子中,我们创建了一个容量为 3 的 ArrayList,并往里面添加了 6 个元素。在添加第 4 个元素时,由于数组已满,系统调用了 grow() 方法进行扩容。下面是 grow() 方法的源码:

private void grow(int minCapacity) {
    // 获取当前 ArrayList 容量
    int oldCapacity = elementData.length;
    // 计算新容量大小
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 如果新容量不足以满足最小容量需求,就使用最小容量作为新容量
    if (newCapacity < minCapacity)
        newCapacity = minCapacity;
    // 创建新的数组,并将原数组的元素复制到新数组中
    elementData = Arrays.copyOf(elementData, newCapacity);
}

可以看到,在扩容时,系统会计算出新的容量大小,并将原数组的元素复制到新数组中,从而保证数据的顺序不变。需要注意的是,在计算新容量大小时,采用了位运算 >> 来代替除法,以提高代码效率。

另外,在调用 grow() 方法扩容时,如果我们向 ArrayList 中添加大量元素,扩容的次数可能很多,从而导致效率降低。因此,我们在使用 ArrayList 时,尽量预留一定的容量,避免频繁扩容。

下面是一个添加 100 000 个元素的例子,可以看到,在初始容量为 100 000 的情况下,并不会出现扩容的情况:

import java.util.ArrayList;

public class Demo {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>(100000);
        for (int i = 0; i < 100000; i++) {
            list.add(i);
        }
    }
}
阅读剩余 27%

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java ArrayList扩容机制原理深入分析 - Python技术站

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

相关文章

  • Java 泛型总结(二):泛型与数组

    Java 泛型总结(二):泛型与数组 在 Java 中,泛型和数组是两个不同的概念,但它们之间的关系比较微妙,需要仔细理解。本篇文章将讲解 Java 泛型和数组的关系,旨在帮助读者更深入理解 Java 泛型的本质。 泛型与数组的不同 泛型是编译期检查的,而数组是运行期检查的。这意味着,我们可以编写泛型代码来确保模板类型的安全性,一旦编译通过,就可以放心使用。…

    Java 2023年5月26日
    00
  • SpringBoot 集成短信和邮件的配置示例详解

    下面我将详细讲解“SpringBoot 集成短信和邮件的配置示例详解”的完整攻略。 1. 集成短信 1.1. 添加依赖 在 pom.xml 中添加阿里云短信 SDK 的依赖: <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-s…

    Java 2023年5月20日
    00
  • Springboot – Fat Jar示例详解

    下面我来详细讲解“Springboot – Fat Jar示例详解”的完整攻略。 简介 首先介绍一下什么是Fat Jar。简单来说,它是一个可以包含应用程序所有依赖库的大型JAR文件,因此它也被称为可执行JAR文件。SpringBoot可以使用Maven或Gradle生成Fat Jar,其他构建工具也支持类似的功能。 在使用Fat Jar时,需要做的就是提供…

    Java 2023年5月19日
    00
  • JSON中fastjson、jackson、gson如何选择

    首先需要了解的是,Fastjson、Jackson和GSON都是流行的JavaJSON库。选择哪个库是根据你的项目、环境需求和个人喜好来决定的。以下是跟进项目、需求以及个人偏好来选择JSON库的攻略: 1. 选择Fastjson Fastjson 是由阿里巴巴开发并维护的 JSON 库,速度快,支持 JavaBean、List、List 等复杂对象的JSON…

    Java 2023年5月26日
    00
  • spring 和 spring boot 中的属性配置方式

    Spring和Spring Boot中的属性配置方式 Spring和Spring Boot都提供了多种属性配置方式,本文将详细介绍这些方式,并提供两个示例。 Spring中的属性配置方式 Spring中的属性配置方式有以下几种: 1. 使用XML配置文件 使用XML配置文件是Spring最早的属性配置方式。在XML配置文件中,我们可以使用元素来定义Bean,…

    Java 2023年5月15日
    00
  • Java构造方法有什么作用?

    Java中的构造方法是一个特殊的方法,它与类的名称相同,且没有返回类型。它主要用于在创建对象时对对象进行初始化操作,也可以用于为一个类的成员变量赋值。构造方法的作用可以总结为以下两点: 1. 对象的初始化 构造方法在创建对象时被调用,用于对对象进行初始化。在Java中,通过关键字new来创建对象时,其实就是创建了这个类的一个实例,同时也创建了一个隐式的构造方…

    Java 2023年5月26日
    00
  • 【C#基础】Substring截取字符串的方法小结(推荐)

    当我们需要截取一个字符串的部分内容时,可以使用C#内置的Substring方法,它可以根据指定的位置和长度,从原始字符串中截取出一个新字符串。 Substring方法的基本使用 Substring方法用于截取字符串的一部分,可以根据指定的位置和长度获取字符串的一部分内容,其基本语法如下: public string Substring(int startIn…

    Java 2023年5月19日
    00
  • Java的Struts框架中Action的编写与拦截器的使用方法

    下面是关于“Java的Struts框架中Action的编写与拦截器的使用方法”的攻略。 Struts框架 Struts是一种流行的MVC(Model-View-Controller)Java Web框架。它允许将应用程序的内容(模型)、用户界面(视图)和应用程序流程(控制器)分开,这样不同的开发人员可以专注于不同的方面。 Action的编写 Action是S…

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