java数组扩容arraylist,ArrayList--扩容机制

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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值