我的编程空间,编程开发者的网络收藏夹
学习永远不晚

JDK1.8中ArrayList是如何扩容的

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

JDK1.8中ArrayList是如何扩容的

ArrayList简介:

ArrayList实现了List接口它是一个可调整大小的数组可以用来存放各种形式的数据。并提供了包括CRUD在内的多种方法可以对数据进行操作但是它不是线程安全的,外ArrayList按照插入的顺序来存放数据。

在讲扩容机制之前,我们需要了解一下ArrayList中最主要的几个变量:


private static final int DEFAULT_CAPACITY = 10;//数组默认初始容量

private static final Object[] EMPTY_ELEMENTDATA = {};//定义一个空的数组实例以供其他需要用到空数组的地方调用 

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//定义一个空数组,跟前面的区别就是这个空数组是用来判断ArrayList第一添加数据的时候要扩容多少。默认的构造器情况下返回这个空数组 

transient Object[] elementData;//数据存的地方它的容量就是这个数组的长度,同时只要是使用默认构造器(DEFAULTCAPACITY_EMPTY_ELEMENTDATA )第一次添加数据的时候容量扩容为DEFAULT_CAPACITY = 10 

private int size;//当前数组的长度

本题的所有的讲解都是基于JDK8

在这里插入图片描述

这道题考察了ArrayList的构造器和对扩容机制的了解,本篇博客基于此出发讲解ArrayList的扩容机制

想要做出这道题必须了解ArrayList的构造函数,ArrayList的构造函数总共有三个:

  • ArrayList()构造一个空的数组。JDK7中构造一个初始容量为10的空列表但是JDK8中只是构造一个空的数组
  • ArrayList(Collection<? extends E> c)构造一个包含指定 collection 的元素的数组,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
  • ArrayList(int initialCapacity)构造一个具有指定初始容量的空数组。

我们重点来看这两个ArrayList(int initialCapacity)ArrayList()构造函数


private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

初始化一个空数组,这是JDK8不同于之前版本的地方


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);
    }
}

对于形参initialCapacity判断,如果大于0那么就声明一个和形参一样大小的数组。了解到这里似乎这道题的正确答案也出来了即选择A,并没有发生扩容

但是作为一名合格的程序员要有探索精神,题目提到了扩容,既然ArrayList底层是一个数组,那么就肯定会满,什么时候发生扩容呢?


//1.add方法为添加元素在数组末尾
public boolean add(E e) {
    //确保数组容量 size指向数组的末尾
    ensureCapacityInternal(size + 1);
    //在完成添加之前要确保数组长度足够
    elementData[size++] = e;
    return true;
}
//3.elementData为ArrayList底层维护的数组,minCapacity为此时数组的大小
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    //如果数组为初始化的值,就初始化数组容量为10(空参的构造方法下首次添加)
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}
//2.minCapacity表示此时数组的大小
private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//4.minCapacity表示此时数组的大小
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    //如果此时数组容量的大小不够就扩容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

源码读到这里,我们明白了,当我们每次向ArrayList添加元素的时候,都会首先确保数组容量够放下元素如果不够就会 grow(minCapacity)调用扩容函数,那么秉承着探索的精神,原本大小的数组扩容之后变成多大了呢?还得继续看源码


//扩容源码
private void grow(int minCapacity) {
    //获取当前数组的长度
    int oldCapacity = elementData.length;
    //>>右移相当于整除2,新容量相当于就旧容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //如果扩容后的容量还不够那么就以需要的容量为新容量
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    //如果新容量已经超过最大容量了,那么就直接使用最大容量
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    //讲新容量的数组拷贝
    elementData = Arrays.copyOf(elementData, newCapacity);
}

源码大致读完后,我们明白了ArrayList的自动扩容机制,每次新添加元素的时候都会判断是否能够容下,如果不够就会发生扩容,扩容的大小为原大小的1.5倍数,明白这些以后让我们看看下面这段程序扩容了几次呢??容量是多少呢?


ArrayList<Integer> arrayList = new ArrayList<Integer>(20);
for(int i=1;i<=50;i++) {
     arrayList.add(i);
}

前20次添加不会发生扩容,当21元素添加时数组容量从20扩容到30,当添加31元素时数组容量从30扩容到45,当添加46元素时数组容量从45扩容到67

到此这篇关于JDK1.8中ArrayList是如何扩容的的文章就介绍到这了,更多相关JDK1.8 ArrayList扩容内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

JDK1.8中ArrayList是如何扩容的

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

JDK1.8中ArrayList是怎么扩容的

本篇内容主要讲解“JDK1.8中ArrayList是怎么扩容的”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JDK1.8中ArrayList是怎么扩容的”吧!ArrayList简介:ArrayL
2023-06-25

java中ArrayList集合的扩容机制是什么

这篇文章主要讲解了“java中ArrayList集合的扩容机制是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java中ArrayList集合的扩容机制是什么”吧!1、扩容要看添加方法,
2023-06-20

ArrayList与linkedList的用法及扩容方式是什么

本文小编为大家详细介绍“ArrayList与linkedList的用法及扩容方式是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“ArrayList与linkedList的用法及扩容方式是什么”文章能帮助大家解决疑惑,下面跟着小编的思路
2023-07-05

如何理解Java容器中ArrayList的源码分析

这篇文章给大家介绍如何理解Java容器中List的源码分析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。如果没有特别说明,以下源码分析基于 JDK 1.8。一、ArrayList1. 概览实现了 RandomAcces
2023-06-05

ArrayList和LinkedList的区别、扩容机制及底层的实现方式是什么

这篇文章主要介绍“ArrayList和LinkedList的区别、扩容机制及底层的实现方式是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“ArrayList和LinkedList的区别、扩容机制
2023-07-05

ArrayList初始化容量的问题如何解决

这篇“ArrayList初始化容量的问题如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“ArrayList初始化容量的
2023-07-05

Win7如何给C盘扩容?Win7给C盘扩容的方式

C盘做为C盘假如存储空间小时会危害电脑上的运转速率,这个时候我们可以根据扩大C盘来处理这个问题,那麼Win7要如何给C盘开展扩容呢?下边就和小编一起来看一下怎么实际操作吧。Win7给C盘扩容的方式1、在网页页面中寻找我的电脑图标。2、鼠标点
2023-07-24

kubernetes中如何实现Pod自动扩容与缩容

小编给大家分享一下kubernetes中如何实现Pod自动扩容与缩容,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一:简介Kubernetes通过HPA控制器,用于实现基本CPU使用率进行自动Pod扩容和缩容的功能。HAP
2023-06-04

ubuntu中lvm扩容的方法是什么

在Ubuntu中,要对LVM逻辑卷进行扩容,可以按照以下步骤进行操作:确保你的磁盘有足够的空间来扩展逻辑卷。使用命令lvdisplay来查看逻辑卷的信息,包括逻辑卷的路径和大小。使用lvextend命令来扩展逻辑卷的大小,例如sudo
ubuntu中lvm扩容的方法是什么
2024-03-08

Golang中map扩容底层如何实现

这篇文章主要讲解了“Golang中map扩容底层如何实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Golang中map扩容底层如何实现”吧!map底层结构主要包含两个核心结构体hmap和
2023-07-05

一文详解Go语言切片是如何扩容的

切片是一个拥有相同类型元素的可变长度的序列,它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。所以本文就来看看Go语言切片是如何扩容的吧
2023-05-15

Java中ArrayList初始化容量大小为10的原因是什么

这篇文章主要讲解了“Java中ArrayList初始化容量大小为10的原因是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中ArrayList初始化容量大小为10的原因是什么”吧
2023-07-02

如何动态删除ArrayList中的元素

这篇文章给大家介绍如何动态删除ArrayList中的元素,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。昨天一位项目组同事需要在ArrayList中删除所有不等于指定值的元素,但是她弄了很久,发现总是删得不完全。刚好我以
2023-06-17

linux如何给已有的分区扩容

要给已有的分区扩容,可以使用以下步骤:1. 确定要扩容的分区。可以使用命令`df -h`查看当前分区的使用情况和剩余空间。2. 卸载该分区。使用`umount`命令,比如`sudo umount /dev/sda1`,将分区卸载。3. 使用
2023-08-25

Java中如何遍历并修改ArrayList中的元素?(在Java中,应如何遍历并修改ArrayList中的元素?)

遍历和修改Java中ArrayList元素的方法有多种,包括:使用集合框架(迭代器、增强型for循环、列表迭代器)使用索引(get()、set()、add()、remove())使用Lambda表达式(forEach()、removeIf())选择方法取决于需求:顺序访问使用迭代器或增强型for循环,随机访问使用索引,简洁代码使用Lambda表达式。
Java中如何遍历并修改ArrayList中的元素?(在Java中,应如何遍历并修改ArrayList中的元素?)
2024-04-02

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录