Java中的ArrayList的初始容量和容量分配

if (elementData.getClass() != Object[].class)

elementData = Arrays.copyOf(elementData, size, Object[].class);

}

二、ArrayList实现自动改变size机制

为了实现这一机制,java引进了Capacity和size概念,以区别数组的length。为了保证用户增加新的列表对象,java设置了最小容量(minCapacity)

,通常情况上,它大于列表对象的数目,所以Capactiy虽然就是底层数组的长度(length),但是对于最终用户来讲,它是无意义的。而size存储着列表

对象的数量,才是最终用户所需要的。为了防止用户错误修改,这一属性被设置为privae的,不过可以通过size()获取。

下面,对ArrayList的初始以及其列表对象的增加和删除等三种情况下的size自动改变机制进行分析。

1、初始Capacity和size值。

从上面给出的ArrayList构造方法源码中,我们不难看出Capacity初始值(initialCapacity)可以由用户直接指定或由用户指定的Collection集合存

储的对象数目确定,如果没有指定,系统默认为10。而size的被声明为int型变量,默认为0,当用户指定Collection创建ArrayList时,size值等于

initialCapacity。

2、add()方法

该方法的源码如下:

public boolean add(E e) {

ensureCapacityInternal(size + 1);

elementData[size++] = e;//添加对象时,自增size

return true;

}

方法中调用的ensureCapacityInternal主要用来调整容量,修改elementData数组的指向。其中涉及到3个方法的调用,其核心在于grow方法:

private void ensureCapacityInternal(int minCapacity) {

modCount++;//定义于ArrayList的父类AbstractList,用于存储结构修改次数

// overflow-conscious code

if (minCapacity - elementData.length > 0)

grow(minCapacity);

}

private void grow(int minCapacity) {

// overflow-conscious code

int oldCapacity = elementData.length;

int newCapacity = oldCapacity + (oldCapacity >> 1);//新容量扩大到原容量的1.5倍,右移一位相关于原数值除以2。

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;//MAX_ARRAY_SIZE和Integer.MAX_VALUE为常量,详细请参阅下面的注解

}

通过以上代码,我们可知java自动增加ArrayList大小的思路是:向ArrayList添加对象时,原对象数目加1如果大于原底层数组长度,则以适当长度新

建一个原数组的拷贝,并修改原数组,指向这个新建数组。原数组自动抛弃(java垃圾回收机制会自动回收)。size则在向数组添加对象,自增1。

注解:

//定义于该类的常量,用来分配数组的size最大值。一些 VMs在数组里保留字头,试图分配更大数组时可能导致OutOfMemoryError:被请求数组的

size超出VM界限。

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

//在java.lang.Integer类中常量MIN_VALUE、MAX_VALUE如下:

public static final int MIN_VALUE = 0x80000000;//整型取值区间下界:-2147483648

public static final int MAX_VALUE = 0x7fffffff;//整型取值区间上界:2147483647

//在java.util.AbstractList中modCount定义如下:

protected transient int modCount = 0;

3、remove()方法

该重构方法其一源码如下(其它的就不累述了):

public E remove(int index) {

rangeCheck(index);

modCount++;

E oldValue = elementData(index);

int numMoved = size - index - 1;

if (numMoved > 0)

System.arraycopy(elementData, index+1, elementData, index,

numMoved);//将后面的列表对象前移

elementData[–size] = null; // 数组前移一位,size自减,空出来的位置置null,具体的对象的销毁由Junk收集器负责

return oldValue;

}

private void rangeCheck(int index) {//边界检查

if (index < 0 || index >= this.size)

throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

}

E elementData(int index) {//获取指定index所在位置的对象

return (E) elementData[index];

}

通过remove()源码的学习,我们不难看出,其改变ArrayList大小的核心与add()方法相似,都是同数组拷贝。

另外,如果确有必要,用户也可以指定ArrayList实例的容量,可以有效的降低时间成本。它是通过调用ensureCapacityInternal来实现的,源代码

如下:

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

做任何事情都要用心,要非常关注细节。看起来不起眼的、繁琐的工作做透了会有意想不到的价值。
当然要想成为一个技术大牛也需要一定的思想格局,思想决定未来你要往哪个方向去走, 建议多看一些人生规划方面的书籍,多学习名人的思想格局,未来你的路会走的更远。

更多的技术点思维导图我已经做了一个整理,涵盖了当下互联网最流行99%的技术点,在这里我将这份导图分享出来,以及为金九银十准备的一整套面试体系,上到集合,下到分布式微服务

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!
67)]

[外链图片转存中…(img-yUpVE7di-1711783654967)]

[外链图片转存中…(img-rT5mAFPm-1711783654968)]

[外链图片转存中…(img-UXGmp73J-1711783654968)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

### JavaArrayListLinkedList的初始容量扩容机制 #### ArrayList初始容量扩容机制 对于 `ArrayList`,当创建对象时不指定初始容量默认情况下其初始容量为10[^2]。每当尝试添加元素而当前内部数组无法容纳更多元素时,就会触发扩容操作。扩容策略是将现有容量扩大至原来的1.5倍(即新的容量等于原容量加上原容量的一半),并把原有数据复制到更大的新空间内[^3]。 ```java // 创建一个默认容量为10的ArrayList实例 ArrayList<String> list = new ArrayList<>(); ``` #### LinkedList 的初始容量扩容机制 不同于 `ArrayList` 使用固定大小的数组作为底层存储结构,`LinkedList` 实际上并不依赖于固定的容量概念,因为它是基于双向链表实现的数据结构[^1]。这意味着每次插入或移除节点时,只需调整相邻结点之间的链接关系即可完成相应操作,无需像 `ArrayList` 那样考虑整体容量的增长问题。因此,在讨论 `LinkedList` 时通常不会提及具体的“初始容量”,而是关注于如何高效地管理动态变化中的节点连接。 然而值得注意的是,虽然 `LinkedList` 不涉及传统意义上的容量扩展过程,但在实际应用过程中仍然存在内存分配行为——每当我们调用方法来增加一个新的节点时,JVM 就会在堆区开辟一块适当的空间用于保存这个新加入的对象实体及其前后指向其他节点的信息字段。 综上所述: - **ArrayList**: 默认初始容量为10;当需要增长时按照约1.5的比例进行扩容。 - **LinkedList**: 没有严格定义的初始容量,依靠链式结构按需分配资源给各个独立节点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值