ArrayList简介

ArrayList是一个动态数组,它的容量可以动态增长,默认容量是10,每次扩容都为原来容量的1.5倍 。 从如下类定义可以看到,它继承了AbstractList,并实现了List/RandomAccess/Cloneable/java.io.Serializable接口

public class ArrayList extends AbstractList

implements List, RandomAccess, Cloneable, java.io.Serializable

1.继承AbstractList和实现List接口,使得ArrayList有了增删改和遍历数组的功能

2.实现RandomAccess接口,即可以随即访问List内的元素,区别于通过Interator迭代器访问

3 这里输入引用文本3.实现java.io.Serializable接口,即可以序列化。

ArrayList两个重要成员变量

1.elementData,是Object[]。Object类型数组里面保存着ArrayList的元素

/**

* Object[]数组,保存ArrayList数据

*/

transient Object[] elementData;

2.size,即ArrayList的实际大小

/**

* ArrayList的实际大小(即保存元素的个数)

*/

private int size;

3个构造器:ArrayList容量的初始化

1.默认构造器 public ArrayList()

2.指定容量的构造器 public ArrayList(int initialCapacity)

3.将其他集合转成ArrayList的构造器 public ArrayList(Collection extends E> c)

其中,默认构造器初始化容量大小为10

/**

* 默认构造函数,初始容量为10

*/

private static final int DEFAULT_CAPACITY = 10;

public ArrayList() {

this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

}

ArrayList源码解析

两个扩容函数,根据 期望容量minCapacity 来扩大ArrayList容量

public void ensureCapacity(int minCapacity) {

/*

* 【minExpand 计算】若 elementData 不为默认大小的空Object[]数组,

* 那么minExpand就为0,否则 minExpand 为 DEFAULT_CAPACITY

*/

int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)

// any size if not default element table

? 0

// larger than default for default empty table. It's already

// supposed to be at default size.

: DEFAULT_CAPACITY;

/*

* 【minCapacity 与 minExpand 比较】当 “期望容量 > 最小可扩展容量” 时

* 根据 期望容量 去扩容。也就是说想要扩容, minCapacity 一定大于 minExpand

*/

if (minCapacity > minExpand) {

ensureExplicitCapacity(minCapacity);

}

}

private void ensureCapacityInternal(int minCapacity) {

/*

* 【确定minCapacity】若ArrayList是默认大小的空Object[]数组,则取

* minCapacity 和 DEFAULT_CAPACITY 中的最大值

*/

if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {

minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);

}

// 直接扩容。根据 期望容量 来扩大ArrayList容量

ensureExplicitCapacity(minCapacity);

}

ensureCapacity()与ensureCapacityInternal()的区别是:

1、前者不一定扩容,只有当minCapacity > minExpand 时扩容(有条件的调用ensureExplicitCapacity())。

2、后者一定扩容(直接调用ensureExplicitCapacity())

当向ArrayList增加元素的时候,判断ArrayList容量是否足够的函数ensureExplicitCapacity() 若 期望容量 > 可用容量,即原ArrayList的可用容量已经不够用了,则调用grow()函数来扩大ArrayList容量,容量大小为minCapacity

private void ensureExplicitCapacity(int minCapacity) {

modCount++; // Increment!

// 若 期望容量 > ArrayList可用容量

if (minCapacity - elementData.length > 0)

// 调用grow()扩容

grow(minCapacity);

}

对于grow(),值得注意的是扩容后新容量的大小:基于原容量*3/2与 期望容量minCapacity大小比较。 若 *3/2 > minCapacity,新容量 = 原容量的3/2 若 *3/2 < minCapacity,新容量 = minCapacity 反正总的一个原则:取值比较大的就对了

???那么问题就来了,是否新容量可以无限大? 函数hugeCapacity()给出了答案,如下。

private void grow(int minCapacity) {

// overflow-conscious code

int oldCapacity = elementData.length;

// 【基于原容量定新容量,且一定执行】新容量 = 原容量*3/2

int newCapacity = oldCapacity + (oldCapacity >> 1);

/*

* 【newCapacity取大 (已经扩容一次了,*3/2)】若 (新容量 < 企图容量) ,

* 则 (新容量 = 企图容量),反正取最大就是了。PS:这次比较的是

* (*3/2)与 minCapacity,取大者

*/

if (newCapacity - minCapacity < 0)

newCapacity = minCapacity;

/*

* 【上限,在合理范围内扩容】这个范围就是数组和整型值的范围,最大值为

* MAX_ARRAY_SIZE(上限) 和 Integer.MAX_VALUE(上限)。

* 若 (企图容量 > MAX_ARRAY_SIZE),那么说明 MAX_ARRAY_SIZE 不能满足

* 需求大小,则用 Integer.MAX_VALUE

*/

if (newCapacity - MAX_ARRAY_SIZE > 0)

newCapacity = hugeCapacity(minCapacity);

// minCapacity is usually close to size, so this is a win:

// 前面千辛万苦得到合适的 newCapacity 后,终于可以开始扩容了,调用 .copyOf()

elementData = Arrays.copyOf(elementData, newCapacity);

}

Integer.MAX_VALUE和 MAX_ARRAY_SIZE之间的关系,如下:

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

可见,Integer.MAX_VALUE > MAX_ARRAY_SIZE > 0,而 扩容后的新容量在(0,Integer.MAX_VALUE]的左开右闭区间内。

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--扩容机制相关推荐

  1. arraylist扩容是创建新数组吗 java_arraylist扩容机制要怎么实现?arraylist怎么扩容...

    ArrayList大家都知道了吧,这是一个动态数组.以java语言来说,数组是定长的,在被创建之后就不能被加长或缩短了,因此,了解它的扩容机制对使用它尤为重要.下面,我们就一起来看看它的扩容机制是怎么 ...

  2. Java集合框架:ArrayList扩容机制解释

    1.java中ArrayList该类的定义 public class ArrayList<E> extends AbstractList<E>implements List&l ...

  3. java基础巩固-宇宙第一AiYWM:为了维持生计,多高(多线程与高并发)_Part9~整起(单双列集合们、ArrayList 的扩容机制、HashMap、ConcurrentHashMap )

    再进入正文之前,先看看集合相关操作的时间复杂度: 本故事源自于~ 开唠: PART0: 为什么突然蹦出集合这个玩意,就是因为咱们基础那里学的"数组"不够用~: 数组一般用来保存一组 ...

  4. 详解java集合之ArrayList——底层实现是一个Object数组。分析ArrayList的自动扩容,原来不一定是1.5倍

    ArrayList的底层实现--非private权限的Object数组 ArrayList的类结构图 1. ArrayList的创建 1.1 参数为空的构造方法--ArrayList内部的Object ...

  5. arraylist 的扩容机制_每天都用ArrayList,你读过它的源码么?

    作者:陌北有棵树,玩Java,架构师社区合伙人! [一]关于扩容 如果没有指定初始容量,则设置为10 /** * Default initial capacity. */private static ...

  6. arraylist 的扩容机制_ArrayList详解

    作者丨HUC南枫 来源丨甲哇技术栈(jiawa1024)ArrayList 的底层是数组队列,相当于动态数组.与 Java 中的数组相比,它的容量能动态增长.在添加大量元素前,应用程序可以使用ensu ...

  7. Java之List系列--ArrayList扩容的原理

    原文网址:Java之List系列--ArrayList扩容的原理_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Java的ArrayList是如何进行扩容的.即:扩容的机制. 重要大小 类 初 ...

  8. 说一说 ArrayList 的扩容机制

    ArrayList有三种方式来初始化,构造方法源码如下: /*** 默认初始容量大小*/private static final int DEFAULT_CAPACITY = 10;private s ...

  9. ArrayList的扩容机制

    在Java中,ArrayList是一个使用非常频繁的集合类型,它的底层是Object数组,所以它拥有数组所拥有的特性,比如支持随机访问,所以查询效率高,但插入数据需要移动元素,所以效率低. 先来看看若 ...

最新文章

  1. MetaPhlAn2-增强版宏基因组分类谱工具
  2. 作为管理者的你,如何用人?一点建议给你
  3. 在r中弄方差分析表_医学统计与R语言: qvalue
  4. php执行删除语句代码,ThinkPHP之数据删除和执行原生SQL语句
  5. 简单的html5 readAsDataURL img和base64互相转换
  6. SOPC第四课 按键中断
  7. 我学员的一个问题及其我对之的解答,关于lr返回值问题
  8. tensorflow包_在Keras和Tensorflow中使用深度卷积网络生成Meme(表情包)文本
  9. 如何正确入门Windows系统下驱动开发领域?
  10. 2021巨量引擎母婴行业白皮书
  11. 揭秘 Python 火爆背后的真实现状,2020 Python 开发者调查
  12. PHP工程师学习计划
  13. socket 怎么设置心跳判断连接
  14. djang常用查询SQL语句
  15. oracle 19c ORA-00942: 表或视图不存在 ORA-02063: 紧接着 line
  16. py.切片(slice)
  17. C模板:十进制和十六进制数据批量转换
  18. matlab函数——meshgrid、mesh、surf函数
  19. 在这款任天堂游戏里,我发现了一部关卡设计的黄金教案
  20. Directory /opt/journalnode/lagou is in an inconsistent state: Can‘t format the storage directo

热门文章

  1. CentOS 7 下安装 mysql ,以及用到的命令
  2. C# 实现ADSL自动断网和拨号(适用于拨号用户)
  3. hdu 1003 A + B Problem II 使用整型数组轻松实现大数求和
  4. qaxobject识别html,QT界面开发-QAxObject 读写excel(COM组件)-常用功能封装代码
  5. 微信小程序_组件学习_001
  6. Spring AOP相关术语解释及简单使用
  7. Dockerfile指令详解:WORKDIR 指定工作目录
  8. linux ssh客戶端:termius介绍及安装
  9. git http仓库账号密码缓存至本地:不用每次git push都需要输入密码的方法(类似于windows的凭据管理)
  10. linux 用journalctl --vacuum-size=10M命令清理/var/log/journal目录下的日志文件