一.ArrayList概述
ArrayList 底层数据结构是基于数组实现的List类,我们知道数组是定长的,但是ArrayList可以动态的增长和缩短索引序列.
基本原理:ArrayList类中封装了一个Object[] 数组 ,数据存放在数组中,size 表示集合中元素个数,每个ArrayList都有一个capacity属性 用来表示数组的长度,默认是10,最大长度Integer.MAX_VALUE - 8,也可以用户自定义数组长度,当添加或者修改元素时 会先调用ensure方法判断集合是否需要扩容,扩容机制是1.5倍
一.ArrayList继承关系
RandomAccess:ArrayList实现了RandomAccess接口,实现这个这个接口的 List 集合是支持快速随机访问的。也就是说,实现了这个接口的集合是支持 快速随机访问 策略的,同时,官网还特意说明了,如果是实现了这个接口的 List,那么使用for循环的方式获取数据会优于用迭代器获取数据。
1、底层使用原生数组实现,实现RandomAccess接口,可以随机访问,随机访问指的是下标索引操作index(i)的时间复杂度是O(1)。size、isEmpty、get、set、iterator和listIterator操作在O(1)内完成,add(e)操作平均在O(1)内完成,即添加n个元素需要O(n)时间(这个是Collection.add,是在尾部添加注意区分下List.add(index, e))。其他操作基本都是O(n)内完成。ArrayList与LinkedList实现相比,O(n)的各个方法的时间复杂度的常数因子更小
2、因为底层数组 elementData 的容量是不能改变的,所以容量不够时,需要把 elementData 换成一个更大的数组,这个过程叫作扩容。实际的元素的数量size,总是不会超过底层数组的容量 elementData.length,因为扩容需要申请更大的内存,并且需要原来数组的进行一次复制,所以扩容是个耗时的操作。在添加大量元素之前,使用者最好是预估一个大致的数量,手动调用ensureCapacity进行一次扩容操作,避免一个个添加导致频繁扩容影响性能。
3、ArrayList是未同步的,多线程并发读写时需要外部同步,如果不外部同步,那么可以使用Collections.synchronizedList方法对ArrayList的实例进行一次封装,或者使用Vector。
4ArrayList实现Iterator,是为了避免ArrayList在迭代过程中数组结构发生变化的而产生的问题,这个处理机制称为Fail-Fast机制,实际是一个乐观锁,实现如下。ArrayList有一个modCount属性,在add(),remove()执行开始,modCount++。ArrayList创建迭代器对象时,会复制当前modCount到expectedModCount,迭代器每次执行next(),remove(),forEachRemaining()时,都判断modCount是否与expectedModCount相同,若不相同,则抛出异常
6、实现Serializable接口,可以被序列化。ArrayList"实现"了自定义序列化方法,这么做主要是为了节省空间 。对于占用空间的大头——元素list,仅仅序列化实际size大小的元素,同时不序列化对于新对象无用属性的——来自父类AbstractList的modCount。ArrayList的实际size不会超过底层数组的length,大多数情况下比底层数组length小,使用默认序列化的话,会直接序列化整个底层数组,序列化后字节流会变大,浪费空间。
二.ArrayList基本参数如下:
三.ArrayList常用方法源码解析
根据角标删除对应元素源码:
根据角标删除对应元素图解,每次指定位置删除或者插入在index后面个元素都需要移动位置,代价很大:
ArrayList实现Iterator,是为了避免ArrayList在迭代过程中数组结构发生变化的而产生的问题,这个处理机制称为Fail-Fast机制,实际是一个乐观锁,实现如下。ArrayList有一个modCount属性,在add(),remove()执行开始,modCount++。ArrayList创建迭代器对象时,会复制当前modCount到expectedModCount,迭代器每次执行next(),remove(),forEachRemaining()时,都判断modCount是否与expectedModCount相同,若不相同,则抛出异常
ArrayList优缺点
优点:
1、因为其底层是数组,所以修改和查询效率高。
2、自动扩容(1.5倍)。
缺点:
1、插入和删除效率不高。(文末对比LinkedList)
2、线程不安全。
三、总结
1)arrayList可以存放null。
2)arrayList本质上就是一个elementData数组。
3)arrayList区别于数组的地方在于能够自动扩展大小,其中关键的方法就是gorw()方法。
4)arrayList中removeAll(collection c)和clear()的区别就是removeAll可以删除批量指定的元素,而clear是全是删除集合中的元素。
5)arrayList由于本质是数组,所以它在数据的查询方面会很快,而在插入删除这些方面,性能下降很多,有移动很多数据才能达到应有的效果
6)arrayList实现了RandomAccess,所以在遍历它的时候推荐使用for循环。
参考:https://www.cnblogs.com/zhangyinhua/p/7687377.html
原文链接:https://blog.csdn.net/luo4105/article/details/88316821