Java集合学习(一)ArrayList源码学习

Java集合学习(一)ArrayList源码学习

前言

侵删,学习记录笔记。并不会写出所有函数的分析,但我会文后放入推荐资料

在Java中,List是一种常用的数据类型,是一种有序的数据结构。

JDK版本

1.8

ArrayList

最常用的List实现类,内部通过数组实现。由于通过数组实现,所以获取元素速度极快,它允许对元素进行快速随机访问对ArrayList的操作并不是线程安全的,建议单线程使用ArrayList,多线程使用Vector或者CopyOnWriteArrayList

ArrayList是一个可以动态增长容量的动态数组。虽然访问速度很快,但数组的缺点是每个元素之间不能有间隔,当数组大小不满足需要扩展容量时,就要将原数组的数据移动到新的存储空间,当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制和移动操作,代价较高。ArrayList适合随机查找和遍历,不适合插入和删除

 List<Integer>list=new ArrayList<Integer>();
    list.add(1);
    System.out.println(list.get(0));

构造方法

在这里插入图片描述

ArrayList() 构造一个初始容量为10的空列表

在这里插入图片描述
在这里插入图片描述

注意,无参构造函数最开始会将elementData这个内部数组引用一个内部static final Object[]空数组,只有第一次进行add操作时才会调用扩容使得elementData扩容成10长度的数组

ArrayList(Collection<? extends E> c)构造一个包含指定元素的列表

ArrayList(int initialCapacity) 构造一个指定初始容量的空列表,

指定的容量必须大于0

add函数

在这里插入图片描述

图 2 ArrayList add函数图

  • add(E e);在列表末尾添加元素
  • add(int index,E e)在指定位置添加元素

分析

在这里插入图片描述

//确保容量是否足够
ensureCapacityInternal(size + 1);
//添加元素,size+1 ,返回true
 elementData[size++] = e;
 return true;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
前面add函数中ensureCapacityInternal(size + 1),传入了size+1并赋值给minCapacity给后续函数用值

calculateCapacity()计算容量,如果当前数组是默认的空数组则从size+1、默认容量(10)中选取最大值并返回,否则返回minCapacity。

ensureExplicitCapacity()函数获取了calculateCapacity()返回的容量,并检查如果calculateCapacity()返回的容量大于当前数组长度,便进行扩容grow()操作。

在这里插入图片描述

首先将数组长度增加到原来数组的一半oldCapacity+oldCapacity/2

如果长度还是不够传入的minCapacity长,则数组扩容到minCapacity长度。

小结

当对数据进行add操作时,会先判断当前数组容量是否足够容纳新元素,不够则会在原有的数组长度下再增加一半长度,如果扩容函数传入的minCapacity仍然大于已经扩容的长度,那就将数组扩容至minCapacity长度

remove(int )函数

在这里插入图片描述

首先判断index是否越界,然后将要删除的元素后面的元素整体往前移动1下标,最后将最后一个位置的数组元素设null,并size-1

get(int )函数

在这里插入图片描述
在这里插入图片描述
判断index是否越界,根据数组下标返回相应元素

clear()函数

在这里插入图片描述

修改次数+1,遍历数组并逐个设null,size设0

ArrayList的序列化以及反序列化

在这里插入图片描述
提问:为什么ArrayList 中 elementData 使用 transient 修饰

答:ArrayList是一个动态数组,由于扩容机制,数组内并非所有空间都被使用,为了防止被自动序列化,便使用transient修饰elementData。同时ArrayList自己实现了序列化和反序列化。

transient :当属性使用transient关键字修饰时,序列化对象时,这个属性不会被序列化

分析

在这里插入图片描述
在这里插入图片描述

在writeObject(java.io.ObjectInputStream s)中,首先将ArrayList.size序列化,然后根据size来序列化数组元素。

在readObject(java.io.ObjectInputStream s)中,根据读取到的size来计算容量 注意calculateCapacity()函数,前文提到过此函数的容量返回机制 来确定是否进行扩容,最后存入反序列化得来的元素。

iterator()

ArrayList自己实现了自己的Iterator

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

后续函数就不截图了,重点关注在函数内部的throw new ConcurrentModificationException();

当修改次数和期望的修改次数不同时,会报多线程异常

参考资料

深入分析java集合ArrayList(源码分析)

java基础之一个 ArrayList 就能让你面试到哭!

《Java核心面试知识整理.pdf》

推荐阅读

Java基础之ArrayList源码分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值