当前位置: 首页 > news >正文

java集合进阶

集合体系结构
Collection集合
List
数据结构
ArrayList
LinkedList
泛型深入
数据结构树
Set系列集合
HashSet
LinkedHashSet
TreeSet

集合体系结构

  • 单列集合:在添加数据时,每次添加一个数据

在这里插入图片描述
List系列集合:添加的元素是有序、可重复、有索引
Set系列集合:添加的元素是无序、不重复、无索引
有序:存进去和取出来的顺序是一样的

  • 双列集合:在添加数据时,每次添加一对数据

Collection

Collection是单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的。
在这里插入图片描述

迭代器遍历

迭代器不依赖索引
迭代器在Java中的类是Iterator,迭代器是集合专用的遍历方式。

Collection集合获取迭代器

在这里插入图片描述

Iterator中常用方法

在这里插入图片描述
细节注意:

  • 报错NoSuchElementException
  • 迭代器遍历完毕,指针不会复位
  • 循环中只能用一次next方法
  • 迭代器遍历时,不能用集合的方法进行增加或者删除
  • 如果我实在要删除:那么可以用迭代器提供的remove方法进行删除。

增强for遍历

所有的单列集合和数组才能用增强for进行遍历。
在这里插入图片描述
修改增强for中的变量,不会改变集合中原本的数据

Lambda表达式遍历

在这里插入图片描述

List

List集合的特点

  • 有序:存和取的元素顺序一致
  • 有索引:可以通过索引操作元素
  • 可重复:存储的元素可以重复’
  • Collection的方法List都继承了
    在这里插入图片描述
    优先调用,实参跟形参类型一致的那个方法。

List集合遍历

  • 迭代器遍历:在遍历的过程中需要删除元素,请使用迭代器
  • 列表迭代器遍历:在遍历的过程中需要添加元素,请使用列表迭代器
  • 增强for遍历
  • Lambda表达式遍历
  • 普通for遍历

数据结构

计算机存储、组织数据的方式
是指数据相互之间是以什么方式排列在一起的。
数据进入栈模型的过程称为:压/进栈
数据离开栈模型的过程称为:弹/出栈

后进先出,先进后出
在这里插入图片描述

队列

先进先出,后进后出
数据从后端进入队列模型的过程称为:入队列
数据从前端离开队列模型的过程称为:出队列
在这里插入图片描述

数组

数组是一种查询快,增删慢的模型

  • 查询速度快::查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中是连续存储的)
  • 删除效率低:要将原始数据删除,同时后面每个数据前移
  • 添加效率极低:添加位置后的每个数据后移,再添加元素。

链表

链表中的结点是独立的对象,在内存中是不连续的,每个结点包含数据值和下一个结点的地址。
链表查询慢,无论查询哪个数据都要从头开始找,

ArrayList

底层原理

  • 利用空参创建的集合,在底层创建一个默认长度为0的数组(elementData)
  • 添加第一个元素时,底层会创建一个新的长度为10的数组(默认null)
  • 存满时,会扩容1.5倍
  • 如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准
    在这里插入图片描述
    在这里插入图片描述

LinkedList

底层数据结构是双链表,查询慢,增删快,但是如果操作的是首尾元素,速度也是极快的
在这里插入图片描述
底层源码
在这里插入图片描述
迭代器底层
在这里插入图片描述

泛型深入

泛型:是IDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。
泛型的格式:<数据类型>
注意:
泛型只能支持引用数据类型,
指定泛型的具体类型后,传递数据时,可以传入该类类型或者其子类类型,
如果不写泛型,类型默认是Object
在这里插入图片描述
扩展知识点:Java中的泛型是伪泛型

泛型很多地方进行定义

  • 类后面–泛型类

使用场景:当一个类中,某个变量的数据类型不确定时,就可以定义带有泛型的类
格式:修饰符 class 类名<类型>{}
在这里插入图片描述
此处E可以理解为变量,但是不是用来记录数据的,而是记录数据的类型,可以写成:T、E、K、V等

  • 方法上面–泛型方法

方法中形参类型不确定时
方案①:使用类名后面定义的泛型,所有方法都能用
方案②:在方法申明上定义自己的泛型,只有本方法能用
格式:修饰符<类型> 返回值类型 方法名 (类型 变量名) {}

  • 接口后面–泛型接口

格式:修饰符 interface 接口名<类型>{
}
使用:
方式1:实现类给出具体类型
方式2:实现类延续泳型,创建对象时再确定

泛型的继承和通配符

  • 泛型不具备继承性,但是数据具备继承性

此时,泛型里面写的是什么类型,那么只能传递什么类型的数据
弊端:利用泛型方法有一个小弊端,此时他可以接受任意的数据类型
此时我们就可以使用泛型的通配符:
?也表示不确定的类型,他可以进行类型的限定
? extends E:表示可以传递E或者E所有的子类类型
? super E :表示可以传递E或者E所有的父类类型
应员场景
1.如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口。
2.如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以泛型的通配符

数据结构树

在这里插入图片描述
在这里插入图片描述
度:每一个节点的子节点数量
二叉树中,任意节点的度<=2
树高:树的总层数
根节点:最顶层的节点

二叉查找树

二叉查找树,又称二叉排序树或者二叉搜索树

  • 每一个节点上最多有两个子节点
  • 任意节点左子树上的值都小于当前节点
  • 任意节点右子树上的值都大于当前节点

添加节点:小的存左边,大的存右边,一样的不存

遍历方式

  1. 前序遍历:从根结点开始,然后按照当前结点,左子结点,右子结点的顺序遍历
  2. 中序遍历:从最左边的子节点开始,然后按照左子结点,当前结点,右子结点的顺序遍历
  3. 后序遍历:从最左边的子节点开始,然后按照左子结点,右子结点,当前结点的顺序遍历
  4. 层序遍历:从根节点开始一层一层的遍历

平衡二叉树

规则:任意节点左右子树高度差不超过1

触发时机:当添加一个节点之后,该树不再是一颗平衡二叉树
旋转机制:

  • 左旋:
    确定支点:从添加的节点开始,不断的往父节点找不平衡的节点
    在这里插入图片描述
    步骤:
           1.以不平衡的点作为支点
           2.把支点左旋降级,变成左子节点
           3.晋升原来的右子节点
    在这里插入图片描述
    步骤:
           1.以不平衡的点作为支点
           2.将根节点的右侧往左拉
           3.原先的右子节点变成新的父节点,并把多余的左子节点出让,给已经降级的根节点当右子节点
  • 右旋
    在这里插入图片描述

步骤:
       1.以不平衡的点作为支点
       2.把支点右旋降级,变成右子节点
       3.晋升原来的左子节点
在这里插入图片描述
步骤:
       1.以不平衡的点作为支点
       2.将根节点的左侧往右拉
       3.原先的左子节点变成新的父节点,并把多余的右子节点出让,给已经降级的根节点当左子节点

旋转的情况

  • 左左:当根节点左子树的左子树有节点插入,导致二又树不平衡,一次右旋
  • 左右:当根节点左子树的右子树有节点插入,导致二叉树不平衡,先局部左旋,在整体右旋
  • 右右:当根节点右子树的右子树有节点插入,导致二叉树不平衡,一次左旋
  • 右左:当根节点右子树的左子树有节点插入,导致二叉树不平衡,先局部右旋,再整体左旋

红黑树

  • 红黑树是一种自平衡的二叉查找树,是计算机科学中用到的一种数据结构。
  • 它是一种特殊的二叉查找树,红黑树的每一个节点上都有存储位表示节点的颜色
  • 一个节点可以是红或者黑;红黑树不是高度平衡的,它的平衡是通过"红黑规则"进行实现的
  • 在这里插入图片描述
    在这里插入图片描述

红黑规则

  1. 每一个节点或是红色的,或者是黑色的
  2. 根节点必须是黑色
  3. 如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的
  4. 如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)
  5. 对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点

添加节点的规则

默认颜色:添加节点默认是红色的(效率高)
在这里插入图片描述

Set系列集合

  1. 无序:存取顺序不一致
  2. 不重复:可以去除重复
  3. 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素

HashSet(无序、不重复、无索引)

Hashset集合底层采取哈希表存储数据
哈希表是一种对于增删改查数据性能都较好的结构

哈希表组成
数组+链表+红黑树

哈希值
对象的整数表现形式
添加数据不是从0索引开始添加的而是通过下面这个公式计算出应存储的位置
在这里插入图片描述

  • 根据hashcode方法算出来的int类型的整数
  • 该方法定义在0bject类,所有对象都可以调用,默认使用地址值进行计算
  • 一般情况下,会重写hashcode方法,利用对象内部的属性值计算哈希值

哈希值特点

  • 如果没有重写上hashcode方法,不同对象计算出的哈希值是不同的
  • 如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
  • 在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)

底层原理
在这里插入图片描述
当数组存了16*0.75=12元素后,会扩容为原先的两倍
JDK8以后,当链表长度超过8而且数组长度大于等于64时自动转换为红黑树
如果集合中存储的是自定义对象,必须要重写hashcode和equals方法
重写hashcode是为了我们根据属性值计算哈希值
重写equals方法是为了比较的时候比较的对象内部的属性值

LinkedHashSet(有序、不重复、无索引)

底层原理
存储和取出的这里的有序指的是保证的元素顺序一致
原理:底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。
在这里插入图片描述

TreeSet(可排序、不重复、无索引)

可排序:按照元素的默认规则(有小到大)排序。
Treeset集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好

集合默认规则

对于数值类型:Integer,Double,默认按照从小到大的顺序进行排序
对于字符、字符串类型:按照字符在ASCII码表中的数字升序进行排序

比较方式

方式一:默认排序/自然排序:Javabean类实现Comparable接口指定比较规则
在这里插入图片描述

方式二:比较器排序:创建Treeset对象时候,传递比较器Comparator指定规则

同时存在以方式二为准

总结:
1.如果想要集合中的元素可重复用ArrayList集合,基于数组的。(用的最多)
2.2.如果想要集合中的元素可重复,而且当前的增删操作明显多于查询用 ,LinkedList集合,基于链表的。
3.如果想对集合中的元素去重用HashSet集合,基于哈希表的。(用的最多)
4.如果想对集合中的元素去重,而且保证存取顺序用LinkedHashSet集合,基于哈希表和双链表,效率低于HashSet
5.如果想对集合中的元素进行排序,用TreeSet集合,基于红黑树。后续也可以用List集合实现排序。

相关文章:

  • Deepseek开源周第五天:3FS-AI界的“数据高速公路“
  • 独立开发者软件出海的法律风险规避指南
  • 深入Linux系列:进程的替换
  • 不再复杂,快速创建RAR文件的简单方法
  • 【Python在校课堂笔记】Python第1节课 【课下总结】
  • Faiss IVFPQ实现
  • 使用Truffle、Ganache、MetaMask、Vue+Web3完成的一个简单区块链项目
  • word有一大段空白就跳到下一页了
  • 算法系列之排序算法-堆排序
  • 五、数据库索引详解:作用、原理与使用指南
  • 11.【线性代数】——矩阵空间,秩1矩阵,小世界图
  • 【时时三省】(C语言基础)字符型数据
  • Redis高可用部署:3台服务器打造哨兵集群
  • 环境会影响你的决策:K近邻算法(KNN)
  • 如何更好地利用Instagram的故事功能提升互动率?
  • AI大模型-提示工程学习笔记17—程序辅助语言模型
  • React实现无缝滚动轮播图
  • RBF神经网络+NSGAII多目标优化算法,工艺参数优化、工程设计优化(Matlab)
  • OpenAI发布GPT-4.5:功能非常特殊,推理很贵
  • 【STL】7.STL常用算法(2)
  • 有没有什么专门做兼职的网站/最新新闻摘抄
  • 网站策划书哪个容易做/三只松鼠软文范例500字
  • phpcms网站seo怎么做/网络营销的概念与特点
  • 泰安网络软件公司/安徽网站seo
  • 在酒吧里做那个视频网站/连云港seo优化公司
  • 武汉最好的网站建设前十/万网创始人