📋 个人简介
- 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者。😜
- 📝 个人主页:馆主阿牛🔥
- 🎉 支持我:点赞👍+收藏⭐️+留言📝
- 📣 系列专栏:java 小白到高手的蜕变🍁
- 💬格言:要成为光,因为有怕黑的人!🔥
目录
- 📋 个人简介
- 前言
- 概述
- 面试题:ArrayList 、 LinkedList 和 Vector 三者的异同?
- 部分类的源码分析
- ArrayList 的源码分析
- LinkedList 的源码分析
- Vector 的源码分析
- 结语
前言
List接口继承自Collection接口,常用的List实现类有ArrayList、LinkedList、Vector。本节将大概对比一下他们三者的不同!并且分析一下源码!
概述
- 鉴于 Java 中数组用来存储数据的局限性,我们通常使用 List 替代数组。
- Lis 集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
- List 容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
- JDKAPI 中 List 接口的实现类常用的有: ArrayList 、 LinkedList 和 Vector 。
因此,我们常常将List接口称作动态数组!
面试题:ArrayList 、 LinkedList 和 Vector 三者的异同?
相同:三个类都实现了List接口,存储数据的特点相同:存储有序的、可重复的数据。
不同:
ArrayList :作为List接口的主要实现类;线程不安全的,效率高,底层使用Object [ ] elementData存储。
LinkedList:对于频繁的插入,删除操作,使用此类会比ArrayList效率高;因为LinkedList底层使用的是双向链表!
Vector:作为List接口的古老实现类;线程安全的,效率低,底层使用Object [ ] elementData存储。
部分类的源码分析
这里我大概分析一下ArrayList和LinkedList的源码,就不详细分析了,之前详细分析了一下StringBuffer的源码。其实和ArrayList差不多,底层都是对数组的扩容。
ArrayList 的源码分析
jdk7和jdk8的ArrayList底层稍有些不同,我用的是较新的jdk17,源码和jdk8基本上是一样的,大概来分析一下吧!
首先当你new ArrayList()之后,会调用空参构造器,创建一个空的,长度为零的数组。
然后往里面添加元素时,会将数组的长度扩容为10。
可以看到,当刚开始长度为零时,执行else分支,将长度扩容为10。==即第一次调用add()时,底层才创建了长度为10的数组,然后将数据添加到了elementDate[0]中。==这也是和jdk7不同之处!。
此时继续添加,容量是够的,不扩容,当添加到数组长度为10时,继续添加就要扩容了,此时进入if分支。
相当于将容量扩大了1.5倍!
总结一下:jdk中ArrayList的对象的创建类似于单例的饿汉式,而jdk8中的ArrayList的创建类似于单例的懒汉式,延迟了数组的创建,节省内存!通过分析源码,我们也可以得出,new ArrayList时建议使用带参数的构造器,即自定义给它初始容量!
LinkedList 的源码分析
前面说了,他的底层是双向链表,这个在数据结构中应该都学过,思想应该都明白,相对于数组而言,链表有利于插入和删除操作,但相对数组而言,链表的查找功能不及数组,数组可以直接取索引,链表要从头查找!
new LinkedList,内部申明了头结点first和尾部节点last,默认为null,添加一个元素后,这个元素即为头结点,又是尾节点。
我们来看看这个Node类型。
再来看看add操作!
看起来很清晰,这里我不再解释,可以自己去了解数据结构的知识!
Vector 的源码分析
Vector已经不常用了,所以这里不再分析源码,感兴趣的可以去看看,分析了这么多源码,应该也能看懂!那我们说ArrayList是线程不安全的,而Vector是线程安全的,我们基本不用Vector,又如何实现线程安全呢?
这个不用担心,即使需要线程安全的场景,我们也不愿意使用Vector,后面会讲到Collections这个工具类,里面有方法可以将ArrayList转变为线程安全的!
结语
如果你觉得博主写的还不错的话,可以关注一下当前专栏,博主会更完这个系列的哦!也欢迎订阅博主的其他好的专栏。
🏰系列专栏
👉软磨 css
👉硬泡 javascript
👉flask框架快速入门