iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java中的ArrayList容量及扩容方式
  • 507
分享到

Java中的ArrayList容量及扩容方式

2024-04-02 19:04:59 507人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录查看jdk1.8ArrayList的源代码1、默认初始容量为102、最大容量为Integer.MAX_VALUE-83、扩容方式:JavaArrayList()扩容原理先看下Ar

查看JDK1.8 ArrayList的源代码

1、默认初始容量为10


   
    private static final int DEFAULT_CAPACITY = 10;

2、最大容量为 Integer.MAX_VALUE - 8


    
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

原因:之前参考别人的,有待求证:

数组对象有一个额外的元数据,用于表示数组的大小;

数组长度size为int类型,共32位,有一位符号位,所以最大长度为Integer.MAX_VALUE=2^31= 2,147,483,648;

8bytes用来存储size;

3、扩容方式:

(1)首先传递进来一个希望的最小容量minCapacity;

(2)新容量newCapacity = oldCapacity + (oldCapacity >> 1),即新容量等于原容量的1.5倍;

(3)如果minCapacity > newCapacity ,newCapacity = minCapacity ;

(4)如果 newCapacity > 最大容量 MAX_ARRAY_SIZE ,newCapacity = hugeCapacity(minCapacity);

(5)以新容量拷贝原数据


   
    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);
    }
 
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

Java ArrayList() 扩容原理

平常都是直接使用 ArrayList(),今天特地看一下 ArrayList() 的扩容原理。

先看下 ArrayList 的属性以及构造方法,这个比较重要

先看下属性


// ArrayList 默认容量大小
private static final int DEFAULT_CAPACITY = 10;
// 一个共享的空数组, 在空实例时使用
private static final Object[] EMPTY_ELEMENTDATA = {};
// 一个共享的空数组, 在使用默认 size 的空实例时使用
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

transient Object[] elementData;
// ArrayList 的大小, 我们平常使用的 list.size() 底层就是记录的这个 size
private int size;
// ArrayList 最大
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

再看构造器,带参构造器



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

参数为 Collection 的构造器



public ArrayList(Collection<? extends E> c) {
    // Collection 转换为数组 Object[] 类型 
    elementData = c.toArray();
    // 判断当前对象大小是否和 Collection 长度相等并且不等于 0, false 的话 elementData 等于空数组了
    if ((size = elementData.length) != 0) {
     // c.toArray() 可能不会正确地返回一个 Object[] 数组,所以使用 Arrays.copyOf()
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

不带参构造器



public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

看到这里就发现,带参的构造器我们可以直接传递参数,而默认的构造器怎么怎么样初始化容量大小的呢?

add() 方法可以直接得到答案。


public boolean add(E e) {
 // 这一行是关键, 看下面
    ensureCapacityInternal(size + 1);
    // 将元素追加到集合的末尾 假如当前 size = 10 size++ 追加到第 11 位
    elementData[size++] = e;
    return true;
}

ensureCapacityInternal() 方法调用


private void ensureCapacityInternal(int minCapacity) {
 
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) { 
 
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
     
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    // 不相等的话只有返回当前的 size + 1
    return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
    // 增量, 记录修改/更新次数
    modCount++;  
    
     // 初始化: 10 - 0 > 0
     // 其他: size + 1 > 0
    if (minCapacity - elementData.length > 0)
     // 扩容操作
        grow(minCapacity);
}
private void grow(int minCapacity) {
    // 老的长度, 初始化时为 0, 
    int oldCapacity = elementData.length;
    // 新的长度此时 0 + (0 >> 1), newCapacity = 0
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 初始化场景: 0 - 10 < 0 ? true newCapacity = 10
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    // 初始化场景: 10 - 2147483639 > 0 返回 false
    if (newCapacity - MAX_ARRAY_SIZE > 0)
     // 超大长度才可以执行这个方法, 必须大于 MAX_ARRAY_SIZE 一般不会
        newCapacity = hugeCapacity(minCapacity);
    // 复制原数组中的元素, 并扩容
    elementData = Arrays.copyOf(elementData, newCapacity);
}

上看说的是初始化场景,下面看一下其他场景,也是相当简单


private void ensureCapacityInternal(int minCapacity) {
 
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) { 
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    
    return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
    // 增量, 记录修改/更新次数
    modCount++;  
    
    // 其他: 11 - 10 > 0 true, 触发扩容, 如果当前下表是 5 的话 5 + 1 =6, 6 < 10 是, 此时不会出发扩容
    if (minCapacity - elementData.length > 0)
     // 扩容操作
        grow(minCapacity);
}
private void grow(int minCapacity) {
    // 老的长度 10
    int oldCapacity = elementData.length;
    // 新的长度此时 10 + (10 >> 1), newCapacity = 15
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 15 - 11 < 0 ? false
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    // 15 - 2147483639 > 0 返回 false
    if (newCapacity - MAX_ARRAY_SIZE > 0)
     // 超大长度才可以执行这个方法, 必须大于 MAX_ARRAY_SIZE 一般不会
        newCapacity = hugeCapacity(minCapacity);
    // 复制原数组中的元素, 并扩容 newCapacity = 15
    elementData = Arrays.copyOf(elementData, newCapacity);
}

结论

1、 触发扩容的关键是

当前 size + 1 是否大于当前容量,如果大于容量则证明,集合不够用了,需要扩容。如果小与当前容量则证明集合还有容量不需要扩容!

2、 每次扩容的大小是


oldCapacity + (oldCapacity >> 1) 即: 10 + (10 >> 1)

即:当前容量的 1.5 倍!

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: Java中的ArrayList容量及扩容方式

本文链接: https://www.lsjlt.com/news/135563.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

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

下载Word文档
猜你喜欢
  • Java中的ArrayList容量及扩容方式
    目录查看JDK1.8ArrayList的源代码1、默认初始容量为102、最大容量为Integer.MAX_VALUE-83、扩容方式:JavaArrayList()扩容原理先看下Ar...
    99+
    2022-11-12
  • ArrayList集合初始化及扩容方式
    目录ArrayList集合初始化及扩容ArrayList 集合ArrayList扩容机制(原理)总结ArrayList集合初始化及扩容 ArrayList 集合 1.默认初始化容量为...
    99+
    2023-03-13
    ArrayList集合初始化 ArrayList扩容 ArrayList初始化
  • ArrayList与linkedList的用法区别及扩容方式
    目录1. Array2. List3. ArrayList4. 使用数组长度分配空间性能对比5. LinkList6. 对比7. ArrayList的源码分析7.1 ArrayLis...
    99+
    2023-03-13
    ArrayList与linkedList区别 ArrayList扩容 ArrayList扩容
  • ArrayList与linkedList的用法及扩容方式是什么
    本文小编为大家详细介绍“ArrayList与linkedList的用法及扩容方式是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“ArrayList与linkedList的用法及扩容方式是什么”文章能帮助大家解决疑惑,下面跟着小编的思路...
    99+
    2023-07-05
  • Java基础之ArrayList的扩容机制
    我们知道Java中的ArrayList对象底层是基于数组实现的,而数组是有长度限制的,那基于数组实现的ArrayList是否有长度限制呢?我们通过ArrayList的构造方法来剖析 ...
    99+
    2022-11-12
  • ArrayList和LinkedList的区别、扩容机制以及底层的实现方式
    目录ArrayList和LinkedList区别、扩容机制及底层实现ArrayListLinkedListVestorArrayList的扩容机制LinkedList的扩容机制Arr...
    99+
    2023-05-13
    ArrayList和LinkedList区别 扩容机制 底层实现
  • JDK1.8中ArrayList是如何扩容的
    ArrayList简介: ArrayList实现了List接口它是一个可调整大小的数组可以用来存放各种形式的数据。并提供了包括CRUD在内的多种方法可以对数据进行操作但是它不是线程...
    99+
    2022-11-12
  • JDK1.8中ArrayList是怎么扩容的
    本篇内容主要讲解“JDK1.8中ArrayList是怎么扩容的”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JDK1.8中ArrayList是怎么扩容的”吧!ArrayList简介:ArrayL...
    99+
    2023-06-25
  • ArrayList集合初始化及扩容方法是什么
    这篇文章主要介绍“ArrayList集合初始化及扩容方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“ArrayList集合初始化及扩容方法是什么”文章能帮助大家解决问题。ArrayList集...
    99+
    2023-07-05
  • 在java中ArrayList集合底层的扩容原理
    目录第一章 前言概述第01节 概述第02节 区别第二章 核心代码第01节 成员变量第02节 构造方法第三章 扩容操作第01节 扩容代码第一章 前言概述 第01节 概述 底层说明 Ar...
    99+
    2022-11-12
  • java中ArrayList集合的扩容机制是什么
    这篇文章主要讲解了“java中ArrayList集合的扩容机制是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java中ArrayList集合的扩容机制是什么”吧!1、扩容要看添加方法,...
    99+
    2023-06-20
  • add方法理解ArrayList的扩容机制
    目录ArrayList的构造方法(前置知识)ArrayList的add方法(理解扩容机制)add 添加元素得到最小扩容量判断是否需要扩容扩容方法ArrayList的构造方法(前置知识...
    99+
    2023-03-07
    add方法ArrayList扩容 add ArrayList
  • ArrayList和LinkedList的区别、扩容机制及底层的实现方式是什么
    这篇文章主要介绍“ArrayList和LinkedList的区别、扩容机制及底层的实现方式是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“ArrayList和LinkedList的区别、扩容机制...
    99+
    2023-07-05
  • 在Java项目中怎么对Arraylist进行动态扩容
    本篇文章为大家展示了在Java项目中怎么对Arraylist进行动态扩容,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。ArrayList 概述ArrayList是基于数组实现的,是一个动态数组,其容...
    99+
    2023-05-31
    java arraylist ava
  • 怎么用add方法理解ArrayList的扩容机制
    这篇文章主要介绍“怎么用add方法理解ArrayList的扩容机制”,在日常操作中,相信很多人在怎么用add方法理解ArrayList的扩容机制问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么用add方法理...
    99+
    2023-07-05
  • Java中HashMap的初始容量设置方式
    Java中HashMap的初始容量设置 根据阿里巴巴Java开发手册上建议HashMap初始化时设置已知的大小,如果不超过16个,那么设置成默认大小16: 集合初始化时, 指定集合初...
    99+
    2022-11-12
  • Java中为什么ArrayList初始化容量大小为10
    目录背景为什么HashMap的初始化容量为16?ArrayList的初始化容量是10吗?为什么ArrayList的初始化容量为10?小结背景 看ArrayList源码时,无意中看到A...
    99+
    2022-11-13
  • Win7如何给C盘扩容?Win7给C盘扩容的方式
    C盘做为C盘假如存储空间小时会危害电脑上的运转速率,这个时候我们可以根据扩大C盘来处理这个问题,那麼Win7要如何给C盘开展扩容呢?下边就和小编一起来看一下怎么实际操作吧。Win7给C盘扩容的方式在网页页面中寻找我的电脑图标。鼠标点击点击我...
    99+
    2023-07-24
  • Java中ArrayList初始化容量大小为10的原因是什么
    这篇文章主要讲解了“Java中ArrayList初始化容量大小为10的原因是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中ArrayList初始化容量大小为10的原因是什么”吧...
    99+
    2023-07-02
  • Java中数组容器(ArrayList)设的计与实现
    目录ArrayList为我们提供了哪些功能设计原理分析代码实现完整代码本篇文章主要跟大家介绍我们最常使用的一种容器ArrayList、Vector的原理,并且自己使用Java实现自己...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作