十、集合(Collection、数据结构、List、泛型深入)
集合概述
-
集合的概述
-
集合和数组都是容器
-
集合是Java种存储对象数据的一种容器
-
-
集合的特点
-
集合的大小不固定,启动后可以动态变化,类型也可以选择不固定。集合像气球
-
集合非常适合做元素的增删操作
-
-
注意:集合中只能存储引用类型数据,如果要存储基本类型数据可以选用包装类
-
集合适合的场景
-
数据的个数不确定,需要进行增删元素的时候。
-
Collection集合的体系特点
-
集合类体系结构
-
Collection单列集合,每个元素(数据)只包含一个值。
-
Map双列集合,每个元素包含两个值(键值对)
-
注意:前期先掌握Collection集合体系的使用
-
-
Collection集合体系
-
Collection(接口)
-
List(接口)
-
ArrayList(实现类)
-
LinkedList(实现类)
-
-
Set(接口)
-
HashSet(实现类)
-
LinkedHashSet(实现类)
-
-
TreeSet (实现类)
-
-
-
-
Collection集合特点
-
List系列集合:添加的元素是有序、可重复、有索引。
-
ArrayList、LinekdList:有序、可重复、有索引
-
-
Set系列集合:添加的元素是无序、不重复、无索引
-
HashSet:无序、不重复、无索引;
-
LinkedHashSet:有序、不重复、无索引
-
TreeSet:按照大小默认升序排序、不重复、无索引
-
-
-
集合对于泛型的支持
-
集合都是支持泛型的,可以在编译阶段约束集合只能操作某种数据类型
-
注意:集合和泛型都只能支持引用数据类型,不支持基本数据类型,所以集合中存储的元素都认为是对象
-
Collection常用API
-
Collection集合
-
Collection是单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的
-
-
Collection API如下:
-
方法名称 说明 public boolean add(E e) 把给定的对象添加到当前集合中 public void clear() 清空集合中所有的元素 public boolean remove(E e) 把给定的对象在当前集合中删除 public boolean contains(Object obj) 判断当前集合中是否包含给定的对象 public boolean isEmpty() 判断当前集合是否为空 public int size() 返回集合中元素的个数 public Object[] toArray() 把集合中的元素,存储到数组中
-
Collection集合的遍历方式
-
迭代器遍历概述
-
遍历就是一个一个的把容器中的元素访问一遍
-
迭代器在Java中的代表是Iterator,迭代器是集合的专用遍历方式
-
-
Collection集合获取迭代器
-
方法名称 说明 Iterator<E> iterator() 返回集合中的迭代器对象,该迭代器对象默认指向当前集合的0索引
-
-
Iterator中的常用方法
-
方法名称 说明 boolean hasNext() 询问当前位置是否有元素存在,存在返回true,不存在返回false E next() 获取当前位置的元素,并同时将迭代器对象移向下一个位置,注意防止取出越界
-
-
增强for循环
-
增强for循环:既可以遍历集合也可以遍历数组
-
它是JDK5之后出现的,其内部原理是一个Iterator迭代器,遍历集合相当于是迭代器的简化写法
-
实现Iterable接口的类才可以使用迭代器和增强for,Collection接口已经实现了Iterable接口
-
-
格式
-
for(元素数据类型 变量名 : 数组或者Collection集合){
-
//在此处使用变量即可,该变量就是元素}
-
-
-
Lambda表达式遍历集合
-
得益于JDK 8 开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式
-
-
Collection结合Lambda遍历的API
-
方法名称 说明 default void forEach(Consumer<? supe T> action) : 结合Lambda遍历集合
-
Collection集合存储自定义类型的对象
-
d4_9
常见数据结构
-
数据结构概述
-
数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的。
-
通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率
-
-
常见的数据结构
-
栈
-
执行特点
-
后进先出,先进后出
-
-
-
队列
-
执行特点
-
先进先出,后进后出
-
-
-
数组
-
查询速度快:查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中是连续存储的)
-
删除效率低:要将原始数据删除,同时后面每个数据前移
-
添加效率极低:添加位置后的每个数据后移,在添加元素
-
-
链表
-
特点
-
链表中的元素是在内存中不连续存储的,每个元素节点包含数据值和下一个元素的地址
-
链表查询慢。无论查询哪个数据都要从头开始找
-
链表增删相对快
-
-
-
二叉树、二叉查找树(二叉排序树、二叉搜索树)
-
二叉查找树特点:
-
每个节点上最多有两个子节点
-
左子树上所有节点的值都小于根节点的值
-
右子树上所有节点的值都大于根节点的值
-
-
二叉查找树目的:
-
提高检索数据的性能
-
-
只有一个根节点,每个节点最多支持两个子节点
-
节点的度,节点拥有的子树的个数,二叉树的度不大于2叶子节点度为0的节点,也称之为终端节点
-
高度:叶子节点的高度为1,叶子结点的父节点高度为2,以此类推,根节点的高度最高
-
层:根节点在第一层,以此类推
-
兄弟节点:拥有共同父节点的节点互称兄弟节点
-
-
平衡二叉树
-
要求
-
任意节点的左右两个子树的高度差不超过1,任意节点的左右两个子树都是一颗平衡二叉树。
-
-
是在满足查找二叉树的大小规则下,让树尽可能矮小,以此提高查数据的性能
-
平衡二叉树-旋转的四种情况
-
左左
-
当根节点左子树的左子树有节点插入,导致二叉树不平衡
-
进行右旋
-
-
左右
-
当根节点左子树的右子树有节点插入,导致二叉树不平衡
-
以出问题的节点进行右旋,在整体左旋
-
-
右右
-
当根节点右子树的右子树有节点插入,导致二叉树不平衡
-
进行左旋
-
-
右左
-
当根节点右子树的左子树有节点插入,导致二叉树不平衡
-
以出问题的节点进行左旋,在整体右旋
-
-
-
-
红黑树
-
红黑树是一种自平衡的二叉查找树,是计算机科学中用到的一种数据结构
-
1972年出现,当时被称之为平衡二叉B树,1978年被修改为如今的”红黑树“
-
每一个节点可以是红或者黑;红黑树不是通过高度平衡的,它的平衡是通过”红黑规则“进行实现的
-
红黑规则
-
每一个节点或是红色,或是黑色,根节点必须是黑色
-
如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为子节点,叶节点是黑色的
-
如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)
-
对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
-
-
添加节点
-
添加的节点的颜色,可以是红色的,也可以是黑色的
-
默认用红色效率高
-
-
红黑树增删改查的性能都很好
-
-
……
-
List系列集合
-
List集合特点、特有API
-
ArrayList、LinkedList:有序,可重复,有索引
-
有序:存储和取出的元素顺序一致
-
有索引:可以通过索引操作元素
-
可重复:存储的元素可以重复
-
-
List集合因为支持索引,所以多了很多索引操作的独特API,其他Collection的功能List也继承了。
-
方法名称 说明 void add(int index,E element) 在此集合中的指定位置插入指定的元素 E remove(int index) 删除指定索引处的元素,返回被删除的元素 E set(int index,E element) 修改指定索引处的元素,返回被修改的元素 E get(int index) 返回指定索引处的元素
-
-
List的实现类的底层原理
-
ArrayList底层是基于数组实现的,根据索引查询元素快,增删相对慢。
-
LinkedList底层基于双链表实现的,查询元素慢,增删首尾元素是非常快的。
-
-
-
List集合的遍历方式小结
-
迭代器
-
增强for循环
-
Lambda表达式
-
for循环(因为List集合存在索引)
-
-
ArrayList集合的底层原理
-
ArrayList底层是基于数组实现的:根据索引定位元素快,增删需要做元素的移位操作
-
第一次创建集合并添加第一个元素的时候,在底层创建一个默认长度为10的数组。
-
-
LinkedList集合的底层原理
-
底层数据结构是双链表,查询慢,首尾操作的速度极快的,所以多了很多首尾操作的特有API
-
LinkedList集合的特有功能
-
方法名称 说明 public void addFirst(E e) 在该列表开头插入指定的元素 public void addLast(E e) 将指定的元素追加到此列表的末尾 public E getFirst() 返回此列表中的第一个元素 public E getLast() 返回此列表中的最后一个元素 public E removeFirst() 从此列表中删除并返回第一个元素 public E removeLast() 从此列表中删除并返回最后一个元素
-
-
补充知识:集合的并发修改异常问题
-
迭代器遍历集合且直接用集合删除元素的时候可能出现
-
增强for循环遍历集合且直接用集合删除元素的时候可能出现
-
哪种遍历且删除元素不出问题
-
迭代器遍历集合但是用迭代器自己的删除方法操作可以解决
-
使用for循环比例删除元素不会存在这个问题
-
补充知识:泛型深入
-
泛型的概述与优势
-
泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查
-
泛型的格式:<数据类型>;注意:泛型只能支持引用数据类型
-
集合体系的全部接口和实现类都是支持泛型的使用的
-
泛型的好处:
-
统一数据类型
-
把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为编译阶段类型就能确定下来
-
-
泛型可以在很多地方进行定义:
-
类后面:泛型类
-
方法申明上:泛型方法
-
接口后面:泛型接口
-
-
-
自定义泛型类
-
概述
-
定义类时同时定义泛型的类就是泛型类
-
泛型类的格式:修饰符 class 类名<泛型变量>{}
-
范例:public class MyArrayList<T>{}
-
此处泛型变量T可以随便写为任意标识,常见的如E,T,V,K,等
-
-
作用:编译阶段可以指定数据类型,类似于集合的作用
-
原理:把出现泛型变量的地方全部替换成传输的真实数据类型
-
-
自定义泛型方法
-
概述
-
定义方法时同时定义了泛型的方法就是泛型方法
-
泛型方法的格式:修饰符<泛型变量> 方法返回值 方法名(形参列表){}
-
范例:public <T> void show(T t){}
-
-
作用:方法中可以使用泛型接受一切实际类型的参数,方法更具备通用性
-
原理:把出现泛型变量的地方全部替换成传输的真实数据类型
-
-
自定义泛型接口
-
概述:
-
使用了泛型定义的接口就是泛型接口
-
泛型接口的格式:修饰符 interface 接口名<泛型变量>{}
-
范例:public interface Data<E>{}
-
-
作用:泛型接口可以让实现类选择当前功能需要操作的数据类型
-
原理:实现类可以在实现接口的时候传入自己操作的数据类型,这样重写的方法都将是针对于该类型的操作
-
-
泛型通配符、上下限
-
通配符:?
-
?可以在“使用泛型”的时候代表一切类型
-
E T K V是在定义泛型的时候使用
-
-
上下限
-
?extends Car:?必须是Car或者其子类 泛型上限
-
?super Car:?必须是Car或者其父类
-
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)