Java源码阅读笔记(一) ArrayList

ArrayList

ArrayList是List集合下的一个实现类,使用数组结构存储数据,该结构缺点是增删操作速度较慢,但查询的速度快。对于需要频繁进行大量查询而对于增删需求不高的数据应选用ArrayList作为数据容器。
ArrayList声明格式:

ArrayList<Integer> arrayList = new ArrayList<>();

需要注意的是:在泛型中需要指定数据类型,不能是基本数据类型。

ArrayList构造方法源码分析

当声明一个无参的构造方法,在ArrayList源码中是这样描述该无参构造方法的:

注释大意是:该无参构造方法初始化一个容量为10的空列表。但点进DEFAULTCAPACITY_EMPTY_ELEMENTDATA查看常量值时却发现,该常量是一个空的数组对象:在这里插入图片描述
因此,通过无参构造方法new的数组其实是一个长度为0的空数组,并不像注释所描述的长度为10的数组,这是怎么回事?在源码的阅读过程中,发现了其中的原因:在使用add方法在ArrayList首次添加元素时,ArrayList会经过算法判断当前的容器长度是否能存下数据,如果不能则对数组长度进行扩容。

Array扩容算法

add方法
在这里插入图片描述
该方法是对外提供的,可在数组最后添加一个元素,且返回值只能是true,也就是说只要调用了这个公有方法,一定会返回true。在该方法中,调用了一个重载的add方法,该方法传入了三个参数,分别是e(要存入的数据)、elementData(存放数据的数组)、size(当前数组的有效数据长度)。
参数在add(e, elementData, size)内部的处理流程是:
在这里插入图片描述
如上所示,首先进行一个判断:s == elementData.length,如果为true代表数组已经存满了,就会调用grow()方法对数组进行扩容;如果为false,直接将赋值给elementData,并将有效数据的长度+1。
grow()方法实际上就是扩容算法,方法返回一个新的经过扩容后的数组,赋值给elementData。
接下来看一下grow()是如何实现数组的扩容:
在这里插入图片描述
grow方法调用了重载的grow方法,将有效数据的长度+1并传入grow(int minCapacity)方法中:在这里插入图片描述
其中,minCapacity代表当前数组最小期望容量,该方法返回一个根据旧数组和新长度为参数复制的一个新数组,旧数组的数据会给到新数组。新长度是通过newCapacity(minCapacity)计算得出:
在这里插入图片描述
在newCapacity中,oldCapcity是数组数据存满时的长度(旧长度),newCapcity新长度等于旧长度的1.5倍。在方法的内部首先进行了一个判断:如果新长度减去期望的长度的结果小于等于0,则代表新长度不足以存数据,此时的策略是:

if(当前数组是否等于初始化的空列表){
	返回 (DEFAULT_CAPACITY(值为10)和 期望容量的最小长度)中的最大值
}
if(期望容量的最小长度小于零){
	抛出内存溢出异常
}
return 期望容量的最小长度

为什么要进行if (newCapacity - minCapacity <= 0)的判断呢?原因在于:如果oldCapcity是0时,newCapcity的长度也会是0,不符合代码逻辑;另外一种情况是如果添加的是一组数据,被添加的一组数据的长度是不可控的,需要进入if语句进行处理。
如果没进if (newCapacity - minCapacity <= 0),说明扩容的长度够用,就会返回:

//判断newCapacity 的值是否大于Array允许的最大长度(int最大值减8)
//如果true直接返回newCapacity
//如果false,需要进入hugeCapacity进行数据处理
return (newCapacity - MAX_ARRAY_SIZE <= 0)
            ? newCapacity
            : hugeCapacity(minCapacity);

hugeCapacity方法的逻辑是:
在这里插入图片描述
如果minCapacity小于0就会抛出内存溢出异常。如果没发生内存溢出异常则再判断minCapacity是否大于Array允许的最大长度,如果大于则返回int类型最大值,如果不大于则返回Array允许的最大长度。

以上就是对ArrayList源码中扩容算法的分析结果。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值