ArrayList的源码分析(一)

我想大家既然能看到这篇文章我就不用解释Arraylist是啥了,简单点说就是一个动态对象数组,然后就这个集合的源代码拿出来给大家分析一下我的个人看法和收获,实例代码是jdk1.8的源代码

首先可以看到,Arraylist这个类继承了AbstractList这个类,实现了list这个接口等等

然后我们来看看它的一些属性: 

从这里可以看到arraylist的默认长度为10,也就是说明当你创建一个arraylist的时候它默认的长度为10

这就是arraylist集合的本体,在这里证明了ArrayList的底层就是对象数组,并且默认是个空的

这是arraylist的长度属性,它的size()方法就是直接返回这个size,这个长度指的是集合的长度,而不是底层对象数组的容量

Arraylist的长度也不是无限的,最大长度为Integer的最大长度-8

扫描二维码关注公众号,回复: 4492437 查看本文章

接下来咱们来看看它的构造方法,:

首先是无参的构造方法,在这里可以看的明天创建了一个长度为10的对象数组,在方法体中的变量在上方都有介绍

第一个有参的构造方法,在这里可以看的出构造方法中的参数就是你创建对象数组的长度,当你使用这个构造方法的时候你就能指定你创建集合的长度,某些情况下这样能优化集合的性能,具体大家可以去看看我的这篇文章:https://blog.csdn.net/qq_41594146/article/details/81870931   如果参数为0的话则依然使用默认的长度10,负数则出现异常

接下来看看第二个有参的构造方法,这里的参数认为只能放Collection的子类,关于泛型大家可以去看我的这篇文章:https://blog.csdn.net/qq_41594146/article/details/82181102    首先将参数集合转成数组用对象数组接收,分两种情况,如果参数集合的长度不是0的话,则继续判断这个数组的类型是不是对象数组,如果不是则复制成一个对象数组,如果该集合的长度为0,那么生成一个为空的arraylist

咱们再来看看我们常用的方法的一些源码,看看到底arraylist怎么样实现动态数组

首先是add方法

这个是我们常用的add方法,直接放一个对象添加到集合中去,然后我一步步跟踪看看它是怎么样添加的

,首先是执行了一个ensureCapacityInternal方法,而它的参数就是当前数组长度加一   elementData是当前集合数组的一个缓冲数组

接下来看看calculateCapacity方法, 如果缓冲数组就是集合本体数组的话,则返回两个参数中较大的一个,参数一为默认长度10

但是如果不是的话就返回当前集合的size+1   

在看看ensureExplicitCapacity方法,这个方法翻译为确保明确的容量,看名字大概也能猜出一点是干啥的.这个判断是如果当前集合长度+1的数减去缓冲数组的长度>0的话执行grow方法,参数为当前集合长度+1,也就是mincapacity

这就是grow方法,  首先用一个int oldCapacity接收,缓冲数组的长度,也就是旧数组的长度,再定义一个新数组的长度newCapacity,这个变量的长度为旧数组的长度加上旧数组的一半的长度,关于这个符号>>大家可以去看我的这篇文章:https://blog.csdn.net/qq_41594146/article/details/81449984   这就是为什么别人说arraylist的扩容机制是1.5倍的所在,后面这两个判断是判断有没有超过容量或者是新数组的长度过小,最后就是一个copy数组的过程,参数1为旧数组,参数2为新数组的长度,  然后用缓冲数组来接收,关于这个缓冲数组的官方介绍:

存储ArrayList元素的数组缓冲区。   ArrayList的容量是此数组缓冲区的长度。添加第一个元素时,任何带有elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA  的空ArrayList都将扩展为DEFAULT_CAPACITY   

也就是说在改变arraylist的数组之后缓冲数组就是集合的底层数组

如果对你有帮助的话可以点下赞,谢谢,后序也将会有更多关于java集合的底层源代码分析   

猜你喜欢

转载自blog.csdn.net/qq_41594146/article/details/84840689