ArrayList底层是数组elementData,用于存放插入的数据。初始大小是0,当有数据插入时,默认大小DEFAULT_CAPACITY = 10。

/**

* The array buffer into which the elements of the ArrayList are stored.

* The capacity of the ArrayList is the length of this array buffer. Any

* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA

* will be expanded to DEFAULT_CAPACITY when the first element is added.

*/

transient Object[] elementData; // non-private to simplify nested class access

什么时候进行扩容?

当插入数据,导致size + 1 > elementData.length,也就是需要从容量超过目前数组长度时,需要进行扩容。

public boolean add(E e) {

ensureCapacityInternal(size + 1); // Increments modCount!! // add一个元素时,size + 1

elementData[size++] = e;

return true;

}

private void ensureCapacityInternal(int minCapacity) {

ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));

}

private void ensureExplicitCapacity(int minCapacity) {

modCount++;

// overflow-conscious code

if (minCapacity - elementData.length > 0)

grow(minCapacity);

}

private static int calculateCapacity(Object[] elementData, int minCapacity) { // 计算新容量

if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 代表elementData数组还是一个空数组,没有任何数据

return Math.max(DEFAULT_CAPACITY, minCapacity); // elementData为空时,会扩容到DEFAULT_CAPACITY = 10和minCapacity的最大值,而minCapacity在插入数据时第一次值为1(size + 1 = 1),会扩容为10

}

return minCapacity;

}

如何扩容?

新数组容量为旧数组的1.5倍:newCapacity = 1.5 * oldCapacity ,并且将旧数组内容通过Array.copyOf全部复制到新数组。此时,size还未真正+1,新旧数组长度(size一致),不过容量不同。

把这里的系数1.5,称作扩容因子k = newCapacity / oldCapacity

/**

* Increases the capacity to ensure that it can hold at least the

* number of elements specified by the minimum capacity argument.

*

* @param minCapacity the desired minimum capacity

*/

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;

}

扩容因子k为何是1.5?

下面举一组对比的例子,取不同扩容因子和初始容量的内存分配情况,当然容量不可能是4,只是方便说明:

k = 2, capacity = 4

0123

01234567

0123456789101112131415

012345678910111213141516171819202122232425262728293031

0123...

k = 1.5, capacity = 4

0123

012345

012345678

0123456789101112

...

k=1.5时,就能充分利用前面已经释放的空间。如果k >= 2,新容量刚刚好永远大于过去所有废弃的数组容量。

为什么不取扩容固定容量呢?

扩容的目的需要综合考虑这两种情况:

扩容容量不能太小,防止频繁扩容,频繁申请内存空间 + 数组频繁复制

扩容容量不能太大,需要充分利用空间,避免浪费过多空间;

而扩容固定容量,很难决定到底取多少值合适,取任何具体值都不太合适,因为所需数据量往往由数组的客户端在具体应用场景决定。依赖于当前已经使用的量 * 系数, 比较符合实际应用场景。

比如,我现在已经用到一个数组100的容量,接下来很可能会有这个数量级的数据需要插入。

为什么是1.5,而不是1.2,1.25,1.8或者1.75?

因为1.5 可以充分利用移位操作,减少浮点数或者运算时间和运算次数。

// 新容量计算

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

java 增长因子_Java ArrayList的扩容因子为什么是1.5?相关推荐

  1. java list负载_java集合的扩容和负载因子的总结

    List 元素是有序的.可重复 ArrayList.Vector默认初始容量为10 Vector:线程安全,但速度慢 底层数据结构是数组结构 加载因子为1:即当 元素个数 超过 容量长度 时,进行扩容 ...

  2. java 遍历方法_Java ArrayList遍历的3种方法

    首页 > 基础教程 > 集合框架 > ArrayList类 Java ArrayList遍历的3种方法 1. Iterator方法遍历 for(Iterator it2 = list ...

  3. java sublist 用法_Java ArrayList subList() 使用方法及示例

    Java ArrayList subList() 使用方法及示例 Java ArrayList subList()方法提取一部分arraylist并将其返回. subList()方法的语法为: arr ...

  4. java isempty用法_Java ArrayList isEmpty() 使用方法及示例

    Java ArrayList isEmpty() 使用方法及示例 Java ArrayList isEmpty()方法用于检查arraylist是否为空. 该isEmpty()方法的语法为: arra ...

  5. java list原理_Java中ArrayList实现原理

    前言 这个分类中,将会写写Java中的集合.集合是Java中非常重要而且基础的内容,因为任何数据必不可少的就是该数据是如何存储的,集合的作用就是以一定的方式组织.存储数据.这里写的集合,一部分是比较常 ...

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

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

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

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

  8. java list原理_Java集合:ArrayList的实现原理

    目录: 一. ArrayList概述: ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单 ...

  9. 【java】为什么 HashMap 的加载因子是0.75?

    1.概述 转载:为什么 HashMap 的加载因子是0.75? 有很多东西之前在学的时候没怎么注意,笔者也是在重温HashMap的时候发现有很多可以去细究的问题,最终是会回归于数学的,如HashMap ...

最新文章

  1. JS中编写函数去除HTML标签,js函数获取html中className所在的内容并去除标签
  2. 使用指针做函数返回值
  3. node重命名文件名_利用Node.js对文件进行重命名
  4. Week1 Team Homework #2 from Z.XML-Introduction of team member with photos
  5. IDEA中无法识别servlet类或找不到javax.servlet.*
  6. linux脚本实现复制,Shell脚本实现复制文件到多台服务器的代码分享
  7. 闯过这 54 关,点亮你的 Git 技能树 (五) - 完结篇
  8. verilog实现多周期处理器之——(六)简单算数操作指令的实现
  9. Linux命令——lsb_release
  10. Flink+Alink,当大数据遇见机器学习! 博文视点Broadview 前天
  11. Linux系统启动过程分析
  12. SQL语句- 条件查询
  13. html网页自动提示框代码,多种网页弹出窗口代码
  14. Guass-seidel 迭代法 matlab实现
  15. Angular—生命周期函数
  16. macOS开启高性能模式
  17. cad哪个版本最好用?思路提供
  18. 2022年系统集成项目管理工程师考试知识点:项目成本管理
  19. 硬盘修复真经 误区、缺陷、参数与低格
  20. IOT设备情况数据分析

热门文章

  1. 华为AppCube入选Forrester《中国低代码平台市场分析报告》
  2. 授人以渔:stm32资料查询技巧
  3. 【华为云技术分享】从自建MongoDB聊聊云数据库MongoDB的蓬勃张力
  4. 华为云MVP:来自工业制造领域的微服务与云平台实践
  5. 基于netty4.x开发时间服务器
  6. 江苏小高考计算机操作题软件,江苏小高考现神题:求微信启动画面的拍摄时间...
  7. opengl学习笔记(六)
  8. LeetCode-116. 填充每个节点的下一个右侧节点指针
  9. LeetCode-567:字符串的排列
  10. php代码实现tp5监听队列,thinkPHP5的队列使用