文章目录
前言
业精于勤荒于嬉,行成于思毁于随;
在码农的大道上,唯有自己强才是真正的强者,求人不如求己,静下心来,开始思考…
今天一起来聊一聊 List集合,看到这里,笔者懂,大家莫慌,先来宝图镇楼 ~
我劝这位小伙子,耗子尾汁。
咳咳… 相信大家满脑子的各种List已被这些经典的画面以及台词冲淡了,那么,目的已达到,那我们言归正传,对于屏幕前帅气的猿友们来说,ArrayList,LinkedList,Vector,CopyOnWriteArrayList… 张口就来,闭眼能写,但是呢,我相信大部分的猿友们并没有刨根问底真正去看过其源码,此时,笔者帅气的脸庞似有似无洋溢起一抹微笑,毕竟是查看过源码的猿,就是那么的不讲武德,吃我一记闪电五连鞭,话不多说,来吧,展示…
一、List类图
二、集合总结
1. ArrayList与Vector集合区别
- 相同点:
-
都实现了List接口;
-
底层采用数组实现;
- 不同点:
-
线程安全方面:
ArrayList线程不安全;
Vector线程安全;
-
扩容方面:
⑴ ArrayList扩容后是原数组长度的1.5倍;
⑵ Vector扩容后是原数组长度的2倍;
-
默认长度方面:
⑴ ArrayList底层数组默认长度为0;
⑵ Vector底层数组默认长度为10;
-
扩容增加容量方面:
⑴ ArrayList不支持自定义;
⑵ Vector中可通过有参构造自定义capacityIncrement增长容量;
2. ArrayList与CopyOnWriteArrayList集合区别
- 相同点:
-
都是实现与List接口;
-
底层采用数组实现;
-
查询效率高,增删效率低;
- 不同点:
-
线程安全方面:
⑴ ArrayList线程不安全;
⑵ CopyOnWriteArrayList集合 add() / remove()方法通过ReentrantLock锁保证线程安全、get()方法线程不安全;
-
扩容方面:
⑴ ArrayList扩容后是原数组长度的1.5倍;
⑵ CopyOnWriteArrayList每次扩容长度为原数组长度+1;
3. 时间复杂度 / 空间复杂度
-
O(1):
O(1)就是最低的时间复杂度了,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空间都不变。 哈希算法就是典型的O(1)时间复杂度,在不考虑冲突的情况下,无论数据规模多大,都可以在一次计算后找到目标;
-
O(n):
时间复杂度为O(n),就代表数据量增大几倍,耗时也增大几倍。比如常见的遍历算法。 要找到一个数组里面最大的一个数,你要把n个变量都扫描一遍,操作次数为n,那么算法复杂度是O(n);
-
O(log n)
时间复杂度为O(log n),当数据增大n倍时,耗时增大log n倍(这里的log是以2为底的,比如,当数据增大256倍时,耗时只增大8倍,是比线性还要低的时间复杂度),二分查找就是O(log n)的算法,每找一次排除一半的可能,256个数据中查找只要找8次就可以找到目标。
-
各集合复杂度:
-
ArrayList:通过下标查询为 O(1),通过遍历数组查询为 O(n);
-
LinkedList:O(n),虽然源码中在查询前进行折半查询,但原理还是全表查找,故为O(n);
-
Vector:通过下标查询为 O(1),通过遍历数组查询为 O(n);
-
CopyOnWriteArrayList:通过下标查询为 O(1),通过遍历数组查询为 O(n);
4. modCount答疑解惑
相信猿友在《不讲武德系列》各篇集合源码分析中都常见到 modCount这个变量,到底什么意思呢,一起分析下:
-
含义:
用来记录当前集合操作次数;
比如在ArrayList,每一次调用add / remove / clear等方法时都会记录一次;
那 modCount 到底是作用来做什么的呢?这里牵扯到另一个重要的概念,Fail-Fast 机制:
-
含义:
Fail-Fast 机制,快速失败机制;
当某一个线程在使用迭代器的过程中,有其他线程修改了modCount,此时会通过modCount是否变化来判断当前线程安全问题,如modCount发生变化则抛出ConcurrentModificationException异常;
注意:此机制出现在使用迭代器的过程中,建议大家使用循环时优先选用迭代器遍历。
三、《不讲武德系列》- 源码分析
1. ArrayList
2. LinkedList
3. Vector
4. CopyOnWriteArrayList
不讲武德,一起聊聊List集合之CopyOnWriteArrayList
~~ 码上福利
大家好,我是猿医生:
在码农的大道上,唯有自己强才是真正的强者,求人不如求己,静下心来,扫码一起学习吧…