Java源码解析-重点集合框架篇

Java 源码解析,集合篇

  • 一:故事背景
  • 二:数据结构
    • 2.1 线性结构
    • 2.2 非线性结构
  • 三:集合分类
    • 3.1 结构图
  • 四:详细分析
    • 4.1 List
      • 4.1.1 ArrayList
        • 4.1.1.1 底层结构
        • 4.1.1.2 主要特点
      • 4.1.2 LinkedList
        • 4.1.2.1 底层结构
        • 4.1.2.2 主要特点
      • 4.1.3 Vector和Stack
        • 4.1.3.1 Vector
        • 4.1.3.1 Stack
  • 五:总结提升

一:故事背景

本文讲解的源码如未经特殊说明,均JDK1.8为准

  • 不知道大家是否听过这么一句话。程序=算法+数据结构。算法指的是解决问题或者指定任务的步骤和规则的有序集合。而数据结构指的是组织和存储数据的方式。
  • 大家可能学过数据结构,可能也经常会使用Java中的集合类。可这些集合类的源码,你真的研究过吗?这篇文章会带着你去学习Java中常用的集合类。从宏观到微观的方式,从使用到源码的方式,带你深入理解Java各个集合类的源码,让你不仅能用集合类,更能用好,能自己去创造集合类。

二:数据结构

想要理解Java中集合类底层使用的数据结构,就要先了解有什么数据结构。本篇文章我们不多做解释,将常见数据结构以及概念罗列,为我们下面分析Java集合源码做铺垫。
我将数据结构分为了两类,分别是线性结构和非线性结构。

2.1 线性结构

线性结构是一种简单的数据结构,其中数据元素之间存在一对一的关系,即每个元素有且只有一个直接前驱和一个直接后继元素,除了第一个元素没有前驱,最后一个元素没有后继。

  • 数组(Array):一组连续存储的数据元素,通过索引访问元素,具有固定大小。
  • 链表(Linked List):由节点组成的数据结构,每个节点包含数据和指向下一个节点的引用。
  • 栈(Stack):一种具有后进先出(Last-In-First-Out,LIFO)特性的数据结构,只能在栈顶进行插入和删除操作。
  • 队列(Queue):一种具有先进先出(First-In-First-Out,FIFO)特性的数据结构,只能在队列的一端插入,在另一端删除。

2.2 非线性结构

非线性结构是指数据元素之间存在多对多的关系,即一个元素可以有多个前驱和后继元素,或者存在层次关系,不像线性结构那样简单的一维排列。

  • 树(Tree):由节点组成的层次结构,每个节点可以有多个子节点,但每个节点只有一个父节点。
  • 图(Graph):由节点(顶点)和边组成,节点之间的关系可以是任意的,可以是双向的,形成复杂的网络结构。
  • 堆(Heap):一种特殊的树结构,常用于优先队列的实现,有最大堆和最小堆两种形式。

三:集合分类

上文讲了常见的数据结构有这么多,那么Java中的集合类都有哪些呢?每个类使用了那种,那几种数据结构呢?今天我们就一起来盘一盘。

3.1 结构图

在这里插入图片描述
Java集合框架主要分为了两类:

  • 以键值对为首的Map类型,其中典型代表为 HashMap
  • 以Collection(收集、聚集)结构为首的。主要有List、Set、Queue、组成。其中List典型代表为 ArrayList和LinkedList、Set代表为HashSet、Queue代表为双端队列ArrayDeque与优先级队列PriorityQueue

四:详细分析

其实这些集合类主要的功能就是用来盛放数据。既然是用来盛放数据那就好办了。

  • 应用层面:我们可以在 增、删、改、查、的四个角度,分析这些不同。
  • 底层层面:我们可以结合数据结构,分析不同的集合类使用的数据结构,结合这些结构的特点,分析这些不同集合类的效率。
    接下来的讲解中,我们不会对各个集合类的增删改查的用法多做研究,而是主要从数据结构与主要特点两个方面进行讲解,更多的从源码、从设计的角度去学习这些集合类。

4.1 List

List 的特点是存取有序,可以存放重复的元素,可以用下标对元素进行操作。

4.1.1 ArrayList

4.1.1.1 底层结构

ArrayList的底层是由数组进行实现的,其内部维护了一个Object类型的数组,数据实际是存在此数组内。
无参构造:
在这里插入图片描述
这里的elementData就是用来存储数据的底层数组:
在这里插入图片描述
DEFAULTCAPACITY_EMPTY_ELEMENTDATA是初始化数组的时候的默认值,默认是空。
在这里插入图片描述
这里大家可能有点小疑问,不对啊,之前我听说ArrayList的默认容量是10,怎么你这里说是空呢。这里就要提到其另外一个特点:
ArrayList是懒加载的,在第一次进行插入数据的时候,才会去开辟空间:
在这里插入图片描述
具体怎么扩容,我们放在下面主要特点里去分析。

4.1.1.2 主要特点

  • 底层由数组实现,支持随机存取(通过下标直接存取)
    上文我们已经看了ArrayList底层的数组,数组的特点就是支持随机存取,取出数据的时间复杂度为O1。这里我们可以看看ArrayList的获取数据的方法:
    在这里插入图片描述

  • 从尾部插入删除元素最快,中间插入删除较慢,头部插入删除最慢。
    这个特点也与数组的特点有关,由于数组是按照顺序存储的,所以在插入或者删除数据的时候,必须要将插入或者删除位置之后的数组进行移动。数组长度固定的情况下,操作的数组越靠前,需要移动的数据就越多。

  • 内部数组容量不足时会自动扩容,元素量非常大的时候,效率较低。
    自动扩容机制,是ArrayList的一个重要特点。每次插入数据的时候都会去检查是否需要扩容,并且扩容为原来容量的1.5倍。
    在这里插入图片描述
    我们主要看检查是否需要扩容这部分
    在这里插入图片描述calculateCapacity方法内部,就是用来检查当前elementData 是否为空,决定是不是要设置为初始容量,这里验证了我们上文所说,只有在第一次Add的时候才会进行实际创建空间。
    在这里插入图片描述
    判断是否需要扩容以及扩容的详细逻辑:
    在这里插入图片描述
    在这里插入图片描述

4.1.2 LinkedList

4.1.2.1 底层结构

LinkedList的底层是一个双向链表结构。通过前后指针维护数据之间的相互关系。其是通过一个内部类进行实现的,内部类里存放了具体的数据,并且维护了前后指针。在这里插入图片描述

4.1.2.2 主要特点

  • 双向链表结构,无法随机存取,只能从一端开始遍历
    双向链表的结构,我们上文已经讲过了,在数据上增加前后指针,使得可以通过指针相互找到。这样的话,在计算机里进行存储就无需逻辑顺序与物理顺序一致。无法随机存取。链表想要在拿到指定位置的数据的话,必须要通过指针进行遍历,找到对应数据所在位置。
    在这里插入图片描述
    在这里插入图片描述
    这里LinkedList做了一个优化,传入索引之后,其不会直接从头开始遍历,而是判断其是存在于前半区,还是后半区。如果在前半区就从前半部分向后开始遍历,后半区从后半区向前遍历。也就是说LinkedList查找在中间部分的数据效率最低

  • 任意位置插入和删除元素非常方便,只需改变应用即可
    需要注意的是,我们这里说的任意位置,是在确定位置的基础上的,找到对应位置,还是无法避免循环。但是与ArrayList相比,LinkedList找到之后,只需要调整前后指针,替换数据即可,不涉及到数据的批量移动。
    在这里插入图片描述
    在这里插入图片描述
    找到数据之后,调整指针与具体数据即可。

  • 需要更多的空间存储上一个节点和下一个节点的引用
    这个就比较容易理解了,因为LinkedList增加了前后指针,指向前后的数据,这些指针会占用额外的存储空间。正是这些指针体现了链表的这种特性。

4.1.3 Vector和Stack

4.1.3.1 Vector

List 的实现类还有一个 Vector,是一个元老级的类,比 ArrayList 出现得更早。ArrayList 和 Vector 非常相似,只不过 Vector 是线程安全的,像 get、set、add 这些方法都加了 synchronized 关键字,因为synchronized锁属于重量级锁,会阻塞其它线程,导致执行执行效率会比较低,所以现在已经很少用了
在这里插入图片描述

4.1.3.1 Stack

Stack 是 Vector 的一个子类,本质上也是由动态数组实现的,只不过还实现了先进后出的功能(在 get、set、add 方法的基础上追加了 pop「返回并移除栈顶的元素」、peek「只返回栈顶元素」等方法),所以叫栈。
在这里插入图片描述
这些我们就不在深入探讨。在实际项目的使用中,如何设计到并发情况下的线程安全问题,关于List,Java提供了线程安全的并发集合容器类CopyOnWriteArrayList。关于这部分,我会出一个详细文章与锁相结合进行讲解,总结。

五:总结提升

本文讲解了重点的集合框架,从源码的层面和数据结构的层面进行了详细分析,通过本文的学习,希望大家对集合框架有一个细致的了解。接下来我会更新常用的并发容器,结合多线程的知识进行分析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/60005.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL5.7数据库、Navicat Premium1.6可视化工具安装教程【详细教程】

文章目录 一、MySQL、Navicat、注册机地址二、安装(一)、MySQL安装(二)、Navicat Premium安装(三)、集活Navicat Premium 三、遇到的问题1、Are you sure your navicat has not beenpatched/modified befor…

计算机是怎么存储和识别人类高级语言的

目录 1、计算机是怎么“存储”人类的高级语言的?2、 UTF-8和UTF-32的区别3、UTF-8是如何区分字节的长度呢?(即如何识别这一串二进制是多少个字节的?)4、计算机是如何识别人类的高级语言的? 1、计算机是怎么…

STM32 CubeMX USB_MSC(存储设备U盘)

STM32 CubeMX STM32 CubeMX USB_MSC(存储设备U盘) STM32 CubeMX前言 《使用内部Flash》——U盘一、STM32 CubeMX 设置USB时钟设置USB使能UBS功能选择FATFS功能 二、代码部分修改代码"usbd_storage_if.c"修改代码"user_diskio.c"main函数初始化插…

node配置Web 服务器

1、什么是 Web 服务器 Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,Web服务器的基本功能就是提供Web信息浏览服务。 它只需支持HTTP协议、HTML文档格式及URL,与客户端的网络浏览器配合。 大多数 web 服务器都支持服…

WebRTC基础知识

文章目录 基础概念NAT (Network Address Translation) 打洞STUN(Session Traversal Utilities for NAT)基于STUN协议的DDoS反射攻击 # TODO TURN(Traversal Using Relays around NAT)ICE(Interactive Connectivity Est…

机器学习---自编码器

自编码器过程 输入一个图片,经过encoder变成一个向量,再通过decoder将这个向量反向生成输入的图片。 这里我们希望输入和输出越接近越好。这个过程我们称为重建。 特点:不需要任何的标注资料。 在2006年这个思想就被提出来了: …

pytorch Stream 多流处理

CUD Stream https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#c-language-extensions 中指出在kenel的调用函数中最后一个可选参数表示该核函数处在哪个流之中。 - 参数Dg用于定义整个grid的维度和尺寸,即一个grid有多少个block。为dim3类型。…

K8S系列文章之 自动化运维利器 Fabric

Fabric 主要用在应用部署与系统管理等任务的自动化,简单轻量级,提供有丰富的 SSH 扩展接口。在 Fabric 1.x 版本中,它混杂了本地及远程两类功能;但自 Fabric 2.x 版本起,它分离出了独立的 Invoke 库,来处理…

Selenium 自动化测试实战笔记1

1. 安装 selenium pip install selenium 3.11.0 # 安装指定版本 pip install selenium -U # 安装最新版本 pip show selenium # 查看当前版本 pip uninstall selenium # 卸载 报错解决1: 带上代理 pip install selenium -i http://mirrors.aliyun.com/…

这些工具让音频文件格式转换更简单

小华是一位音乐爱好者,他平时喜欢下载并播放一些流行音乐。在这个过程中,他发现从不同平台上下载下来的音乐格式并不一样,而不同的播放平台也支持不同的音频格式。这令他感到烦恼,并希望通过一些音频格式转换器来帮助他解决音频格…

基于springboot+vue的幼儿园管理系统的设计与实现_5umt6

随着世界经济信息化、全球网络化的到来推动信息线上管理的飞速发展,为幼儿园行业的改革起到关键作用。若想达到安全,快捷的目的,就需要拥有信息化的组织和管理模式,建立一套合理、畅通、高效的幼儿园管理系统。当前的幼儿园管理系…

实例033 制作闪烁的窗体

实例说明 Windows系统中,当程序在后台运行时,如果某个窗口的提示信息需要用户浏览,该窗口就会不停的闪烁,这样就会吸引用户的注意。同样,如果在自己的程序中使某个窗口不停的闪烁就会吸引用户的注意。本例设计了一个闪…