ArrayList手写前的源码整理

简单说明下:ArrayList是一个数组队列,相当于动态数组,与java中的数组相比能动态增长。

特点:

1.随机访问速度快,插入和移除性能较差

2.支持null

3.有顺序

4.元素可以重复

5.线程不安全

想要手写一个ArrayList必须了解他的底层逻辑,我把我的理解整理的下

首先看看源码

(以下为1.8环境的源码)

ArrayList手写前的源码整理

 

首先这里可以看到有两个空数组,先来看一下这两个空数组的区别

ArrayList手写前的源码整理

ArrayList手写前的源码整理

从两个构造函数可以看到无参构造将内置数组指向了长空数组,当传入参数为0时将内置数组指向了短空数组。

下面用代码看一下区别,这里用反射查看了内置数组的长度

ArrayList手写前的源码整理

ArrayList手写前的源码整理

当添加一个元素后

ArrayList手写前的源码整理

ArrayList手写前的源码整理

可以看到无参构造指向的长空数组长度变为了10,而短空数组变为了1,既然是在add操作之后发生了变化,那么就去看看add的源码吧。

ArrayList手写前的源码整理

ArrayList手写前的源码整理

这有个属性为modCount

ArrayList手写前的源码整理

他是在父级AbstractList中声明的,通过注释可以知道这个参数是修改次数标识

接着看代码,

ArrayList手写前的源码整理

可以看到grow是将内置数组扩容的操作,首先扩容为原大小的1.5倍取整

而后可以看到若是无参构造指向的长空数组,便扩容至10

jdk1.6的构造函数如下,可以看到直接初始化为长度10的空数组

ArrayList手写前的源码整理

而1.8是添加第一个元素是才将大小扩充至10。

而后又做了一步判断,数组的最大长度为Integer的最大值-8

由注释可以看到这是为了防止机器内存溢出

另外也防止了int形溢出变为负数的情况

a-b>0不等价于a>b

a=Integer.MAX_VALUE+10

b=Integer.MAX_VALUE-10

a-b>0—>true

a>b—>false

看完add再看看其他

ArrayList手写前的源码整理

ArrayList手写前的源码整理

Get方法,首先判断下标是否越界,然后将该下标的数组元素返回

ArrayList手写前的源码整理

set方法,首先判断下标是否越界,然后将原元素返回,新元素替换(set操作并没有使modCount++)

ArrayList手写前的源码整理

ArrayList手写前的源码整理

由此可以看到带下标的add操作是把该下标以后的元素都往后移一位,而后把新元素插到空出来的index位

ArrayList手写前的源码整理

remove操作相当于先获取所有该元素的下标,然后一个个删除

删除操作就是将该下标以后的元素都往前复制移动一位,然后将原来的最后一位设为null等待GC回收

ArrayList手写前的源码整理ArrayList手写前的源码整理

而后将最后一个5设为null等待GC回收

 

看了源码之后相比再手写一个ArrayList就再轻松不过了!