java对字符数组动态扩容,java的ArrayList动态扩容机制(JDK8)

要了解ArrayList的动态扩容机制,查看了解ArrayList中的add方法是必不可少的,add方法源码如下:

/**

* Appends the specified element to the end of this list.

*

* @param e element to be appended to this list

* @return true (as specified by {@link Collection#add})

*/

public boolean add(E e) {

ensureCapacityInternal(size + 1); // Increments modCount!!

elementData[size++] = e;

return true;

}

其中 ensureCapacityInternal(size + 1); 便是ArrayList的动态扩容机制,ensureCapacityInternal方法源码如下:

private void ensureCapacityInternal(int minCapacity) {

ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));

}

ensureCapacityInternal方法依靠调用ensureExplicitCapacity 方法实现动态扩容,在调用ensureExplicitCapacity 方法之前,java还调用了calculateCapacity(elementData, minCapacity),下面将逐一分析,首先看calculateCapacity(elementData, minCapacity)里面都做了什么吧。

private static int calculateCapacity(Object[] elementData, int minCapacity) {

if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {

return Math.max(DEFAULT_CAPACITY, minCapacity);

}

return minCapacity;

}

先看入参,其中elementData便是ArrayList真正用于存储元素的数组,minCapacity代表elementData数组的新长度(原数组长度+要增加的数组长度),add方法意在ArrayList尾部加入新元素,那么此时ArrayList的minCapacity便是size+1,其中size表示此ArrayList实际存储数据元素的个数。

calculateCapacity 方法判断ArrayList默认的元素存储数据是否为空,其中DEFAULTCAPACITY_EMPTY_ELEMENTDATA源码如下:

/**

* Shared empty array instance used for default sized empty instances. We

* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when

* first element is added.

*/

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

如果elementData为空,则返回传入的minCapacity和DEFAULT_CAPACITY中的最大值,其中DEFAULT_CAPACITY为elementData数组的默认长度:

/**

* Default initial capacity.

*/

private static final int DEFAULT_CAPACITY = 10;

如果elementData不为空,则返回传入的minCapacity;以上便是calculateCapacity 执行的完整过程。

总结如下:

calculateCapacity方法完成了一件事,如果当前ArrayList存储数据元素的数组为空,则表示当前ArrayList可能为初始的ArrayList(未加入数据),此时只需返回默认的elementData数组的长度与你希望的数组新长度的较大值(因为ArrayList扩容是有性能损耗的,所以扩容的大小在合理范围内越大,将来扩容的次数就越小),如果此时ArrayList的elementData不为空,则直接返回你希望的数组新长度即可,calculateCapacity方法的返回值记为数组实际的新长度。

然后我们在分析ensureExplicitCapacity(calculateCapacity(elementData, minCapacity))方法,ensureExplicitCapacity方法源码如下:

private void ensureExplicitCapacity(int minCapacity) {

modCount++;

// overflow-conscious code

if (minCapacity - elementData.length > 0)

grow(minCapacity);

}

入参minCapacity即为calculateCapacity方法处理后的数组实际的新长度,ensureExplicitCapacity方法先进行数组实际的新长度是否比当前存储数据的数组(elementData)长度大的判断,即判断当前ArrayList的长度是否够用,是否需要扩容。

if (minCapacity - elementData.length > 0)

如果需要扩容,则调用grow(minCapacity)方法进行扩容

/**

* 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); //数组原长度*1.5

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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值