【 java 集合】List接口常用实现类对比以及ArrayList和LinkedList源码分析

news/2024/11/28 8:33:23/

📋 个人简介

  • 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者。😜
  • 📝 个人主页:馆主阿牛🔥
  • 🎉 支持我:点赞👍+收藏⭐️+留言📝
  • 📣 系列专栏: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框架快速入门


http://www.ppmy.cn/news/9353.html

相关文章

【机器学习】线性回归损失函数为什么要用平方形式

问题 线性回归损失函数为什么要用平方形式? 问题背景 这是在阿里一面中遇到的问题,当时我的回答是损失函数是是模型预测值与真实值之间的一种距离度量,我们可以计算出每个样本的预测值与真实值之间的距离,全部加起来就得到了所…

【MySQL】-【索引】

目录为什么使用索引InnoDB中索引的推演索引前的查找设计索引简单的索引设计方案InnoDB中的索引方案为什么使用索引 一、hashmap底层使用红黑树 二、索引时在存储引擎中实现的,因此不同存储引擎的索引可能不同 索引的优点: 类似大学图书馆建书目索引&am…

景联文科技:探究人工智能在智慧医疗中的应用及作用|数据标注

智慧医疗中的人工智能具有难以想象的潜力。人工智能在智慧医疗中的未来从通过协助重复性工作到药物管理或药物创造的治疗计划设计开始,人工智能已经在多个医学领域发挥作用。更好地组织智慧医疗物流智慧医疗和医学领域的人工智能可以更好地组织患者路线或治疗计划&a…

机器学习实战教程(九):支持向量机实战篇

一、前言 上篇文章讲解的是线性SVM的推导过程以及简化版SMO算法的代码实现。本篇文章将讲解SMO算法的优化方法以及非线性SVM。 本文出现的所有代码,均可在我的github上下载,欢迎Follow、Star:点击查看 二、SMO算法优化 在几百个点组成的小规…

扩展欧几里得算法 - exgcd

学exgcd的时候没好好听课,几乎每次遇到都忘记。 于是打算写篇博客。 扩展欧几里得算法,就是欧几里得算法的扩展。 欧几里得算法,就是 gcd,共产党 ,用来求最大公约数的。 还是一样,首先搞明白他是干啥的。…

到底为什么那么多大厂在开始疯狂裁员?

最近几年大家都听到了好多大厂公司开始裁员,比如鹅厂、狗厂、鸟厂、熊厂等。 接下来给大家讲个故事,希望故事看完,你就会懂了! 外国的神父呆了不久 留下几个 P 就走了, 一个 P 叫 BPR, 一个 P 叫 ERP。 …

c++下 ADO+配置数据源连接oracle数据库

测试环境:在本地局域网内远程连接服务器端的oracle数据库,VS2013、ADO方式。2、本地安装oracle数据库客户端,具体是安装32位还是64位的数据库客户端,取决于我们编译的程序是32位的还是64位的(和计算机的系统位数没有关…

【EHub_tx1_tx2_E100】Ubuntu18.04 + ROS_ Melodic + NVISTAR VP300 激光雷达 评测

简介:介绍NVISTAR 的二维DTOF激光雷达 在EHub_tx1_tx2_E100载板,TX1核心模块环境(Ubuntu18.04)下测试ROS驱动,打开使用RVIZ 查看点云数据,本文的前提条件是你的TX1里已经安装了ROS版本:Melodic。…