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

数据结构(Java):Map集合Set集合哈希表

目录

1、介绍

1.1 Map和Set

1.2 模型

2、Map集合

2.1 Map集合说明

2.2 Map.Entry<K,V>

2.3 Map常用方法

2.4 Map注意事项及实现类

 3、Set集合

3.1 Set集合说明

 3.2 Set常用方法

 3.3 Set注意事项及其实现类

4、TreeMap&TreeSet

4.1 集合类TreeMap(Key-Value模型)

4.1.1 底层结构

4.2 集合类TreeSet(纯Key模型)

4.2.1 底层结构

4.3 TreeMap与TreeSet之间的关系

4.3.1 再谈TreeSet之构造方法

 4.3.2 再谈TreeSet之add方法

4.4 TreeMap&TreeSet总结

 5、哈希表

5.1 概念

5.2 冲突-概念

5.2 冲突-避免

5.2.1 设计合理的哈希函数

 5.2.2 调节负载因子

5.3 冲突-解决

5.3.1 闭散列

 5.3.2 🌟开散列/哈希桶/开链法

5.4 HashMap&HashSet

5.4.1 hashCode与equals方法

5.5 性能分析

5.6 总结


1、介绍

1.1 Map和Set

Map和Set是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关。

Map和Set能够在查找时进行一些插入和删除的操作,即动态查找。

1.2 模型

一般把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称之为Key-value的键值对,所以模型会有两种:

  1. 纯Key模型:数据仅包含关键字。
  2. Key-Value模型:数据除关键字外,还有关键字所对应的值。例如:统计文件中每个单词出现的次数,统计结果是每个单词都有与其对应的次数:<单词,单词出现的次数>。

 Map集合是Key-Value模型;而Set集合是纯Key模型。


2、Map集合

2.1 Map集合说明

Map是一个接口类,该接口没有继承自Collection,是一个单独的接口,为Key-Value模型,存储的是<K,V>结构的键值对,并且K一定是唯一的,不能重复。  (K不可重复,V可重复)

2.2 Map.Entry<K,V>

Entry是Map接口的一个内部接口是用来存放<Key,Value>键值对映射关系的内部接口

内部接口Map.Entry<K,V>主要提供了<Key,Value>的获取,Value的设置以及Key的比较方式。

注意:Map.Entry<K,V>并没有提供设置Key的方法 !!!Key无法修改!!!

同样,实现Map接口的类也需要实现Entry接口:

这里以TreeMap的内部类Entry为例,Entry实现了的Map.Entry接口,而Entry就相当于我们之前所学二叉树的一个节点TreeNode。

TreeMap的底层是一个红黑树(下文详解),TreeMap的内部类Entry就相当于红黑树的一个节点,有key、value等属性。

2.3 Map常用方法

 演示如下:

若我们使用get方法来获取一个不存在的key的value值时,返回的value为null,

所以当value为Integer类型时,最好使用包装类Integer接收,若使用int基本类型接收会自动拆箱,可能抛出空指针异常:

需要注意的是keySet、values、entrySet方法:

  • keySet,可以将key值放在Set集合中,返回Set集合;
  • values,可以将value值放在Collection集合中,返回Collection集合;
  • entrySet,可以将key-value映射关系放在Set集合中,返回Set集合。

注意:Map系列集合是不能用迭代器实现遍历的,若想使用迭代器遍历,需要使用keySet、values、entrySet方法转换为Set集合,再使用迭代器遍历!!!

2.4 Map注意事项及实现类

  1. Map是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类TreeMap或者HashMap
  2.  Map中存放键值对的Key不能重复,value是可以重复的
  3. 在TreeMap中插入键值对时,key不能为空,否则就会抛NullPointerException异常,value可以为空。(TreeMap底层是一颗红黑树,涉及key之间的比较)
  4. HashMap的key和value都可以为空。
  5. Map中的Key可以全部分离出来,存储到Set中来进行访问(Key不能重复)。
  6. Map中的value可以全部分离出来,存储在Collection的集合中,若存储在其子集中则强转为Collection(value可以有重复)。
  7. Map中键值对的Key不能直接修改,value可以修改,如果要修改key,只能先将该key删除掉,然后再来进行重新插入。 
  8. TreeMap和HashMap是实现Map的集合类

 TreeMap与HashMap:

下文细讲TreeMap与HashMap。 


 3、Set集合

3.1 Set集合说明

Set集合是纯Key模型,也就是说,Set只存储了Key。

Set集合中的Key值也不能重复存在,能够达到天然去重的效果。

Set与Map主要的不同有两点:

  1. Set是继承自Collection的接口类。
  2. Set是纯Key模型,只存储了Key。

 3.2 Set常用方法

因为Set是是继承自Collection的接口类,所以其方法很多与我们之前学的Collection接口下的类是相同的,这里不再赘述。

需要注意的是:

  • 如果将其他集合的元素添加到Set集合中,可以到达天然去重的效果;
  • Set集合可以使用迭代器遍历;

 3.3 Set注意事项及其实现类

  1. Set是继承自Collection的一个接口类。
  2. Set中只存储了key,并且要求key一定要唯一
  3. TreeSet的底层是使用TreeMap来实现的,其使用Key与Object的一个默认对象作为键值对插入到Map中。
  4. Set最大的功能就是对集合中的元素进行去重
  5. 实现Set接口的常用类有TreeSet和HashSet(下文细讲),还有一个LinkedHashSet,LinkedHashSet是在HashSet的基础上维护了一个双向链表来记录元素的插入次序。
  6. Set中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入
  7. TreeSet中不能插入null的key(底层为搜索二叉树,涉及key的比较),HashSet可以。

 TreeSet与HashSet:


4、TreeMap&TreeSet

 为什么要将TreeMap和TreeSet放到一起说呢?因为这两者间是有关系的。

4.1 集合类TreeMap(Key-Value模型)

4.1.1 底层结构

TreeMap是Map集合下的一个集合类,底层是一颗红黑树,红黑树是一颗二叉搜索树,所以其Key值必须具备可比较功能。

也就是说,如果其Key是自定义类型,则这个自定义类必须实现Comparable接口或者给TreeMap的构造方法提供比较器。

 因为TreeMap底层为红黑树,故其插入删除查找元素的时间复杂度为O(logN)

4.2 集合类TreeSet(纯Key模型)

4.2.1 底层结构

TreeSet是Set集合下的一个集合类,底层也是一颗红黑树,红黑树是一颗二叉搜索树,所以其Key值也必须具备可比较功能。

故,TreeSet插入删除查找元素的时间复杂度也为O(logN)

同样,如果其Key是自定义类型,则这个自定义类必须实现Comparable接口或者给TreeSet的构造方法提供比较器。

4.3 TreeMap与TreeSet之间的关系

虽然TreeMap是Map下的集合,TreeSet是Set下的集合,

但是细心的小伙伴已经发现,TreeMap和TreeSet的底层结构不仅都是红黑树,而且他们的Key值都不能重复出现,那么他们之间是不是有什么关系呢?

没错,其实TreeSet的底层是使用TreeMap来实现的。

可是为什么呢?接下来,让我们从TreeSet的源码中找到原因。

4.3.1 再谈TreeSet之构造方法

我们可以看到,当我们调用TreeSet的无参构造方法创建TreeSet对象时,其实是创建了一个TreeMap对象并传给了带一个参数的构造方法,并用NavigableMap类型的成员变量m将这个TreeMap对象引用起来。

NavigableMap是什么呢,我们点过去后发现是一个接口,并且拓展了SortedMap接口,而我们发现SortedMap接口拓展了Map接口

我们再观察TreeMap,发现TreeMap实现了NavigableMap接口。

所以,其实TreeMap有着下图的实现结构:

也就是说NavigableMap可以用来接收TreeMap对象实现向上转型,同时也说明,当我们实例化一个TreeSet对象时,实际上创建的是一个TreeMap对象。

也就是说,TreeSet的底层其实就是TreeMap!!!

 4.3.2 再谈TreeSet之add方法

因为TreeSet的底层是TreeMap,所以添加元素add时,实际上调用的是TreeMap的put方法,而其value值是PRESENT,而PRESENT永远都是一个Object对象。 

 

所以,不管add的Key是什么东西,其value值永远都是一个Object对象。

4.4 TreeMap&TreeSet总结

  •  TreeMap底层是一颗红黑树,二叉搜索树。
  • TreeSet的底层是TreeMap,所以TreeSet也是一颗红黑树,二叉搜索树。
  • TreeSet的底层是TreeMap,所以其Key不可重复,具有Map的去重功能。

 5、哈希表

5.1 概念

在顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经过关键码(Key)的多次比较。顺序查找时间复杂度为O(N),平衡树中为树的高度即O(logN),搜索的效率取决于搜索过程中 元素的比较次数。

而哈希表可以通过哈希函数使元素的存储位置与它的关键码之间能够建立一一映射的关系,不经过任何比较,一次直接从表中得到要搜索的元素。

该方式即为哈希(散列)方法,哈希方法中使用的转换函数称为哈希(散列)函数,构造出来的结构称为哈希表(或者称散列表)。

插入元素:

  • 根据待插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放

查找元素:

  • 对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比较,若 关键码相等,则搜索成功 

哈希表 插入/删除/查找操作的时间复杂度为 O(1)。

5.2 冲突-概念

不同关键字通过相同哈希函数计算出相同的哈希地址,该种现象称为哈希冲突或哈希碰撞。

 把具有不同关键码而具有相同哈希地址的数据元素称为"同义词"。

 由于我们哈希表底层数组的容量往往是小于实际要存储的关键字的数量的,

这就导致一个问题:冲突的发生是必然的,但我们能做的应该是尽量的降低冲突率

5.2 冲突-避免

避免冲突有两个办法,一个是设计合理的哈希函数,一个是调节负载因子。

5.2.1 设计合理的哈希函数

哈希函数设计原则:

  1. 哈希函数的定义域必须包括需要存储的全部关键码,而如果散列表允许有m个地址时,其值域必须在0到m-1之间
  2. 哈希函数计算出来的地址能均匀分布在整个空间中
  3. 哈希函数应该比较简单

常见哈希函数:

 注意:哈希函数设计的越精妙,产生哈希冲突的可能性就越低,但是无法避免哈希冲突

在实际应用中,其实也轮不到我们来设计哈希函数...hhh😂

 5.2.2 调节负载因子

负载因子的计算公式为:负载因子 = 已有键值对数量 / 散列表容量。

它表示在散列表中,当插入一个新的键值对时,可以允许的最大填充程度。

负载因子越大,散列表的填充程度越高,冲突的发生率越高。相反,负载因子越小,散列表的填充程度越低,插入和查找操作的性能可能会更好,冲突的发生率越低,但空间利用率会降低。

因为我们不能降低元素填入个数,所以我们只能扩容哈希表来降低冲突率。

当元素个数和散列表容量的比值接近或等于负载因子时,就要对哈希表进行扩容操作。

换句话说,哈希表就是以空间换取时间的一种数据结构。

Java中,定义的负载因子大小为0.75。

5.3 冲突-解决

我们知道,冲突的发生是必然的,那么,当冲突发生后,我们该如何做呢?

解决哈希冲突两种常见的方法是:闭散列和开散列。

5.3.1 闭散列

闭散列:也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把key存放到冲突位置中的"下一个"空位置中去。

找"下一个”"空位置,有两种方法: 

  • 线性探测法:从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止。(线性探测的缺陷是产生冲突的数据堆积在一块)
  • 二次探测法:采用移动数值的平方次来找空位置。例如:如果键15的哈希值对应的空间已经被占用,算法可能会尝试使用平方数序列(如1^2, -1^2, 2^2, -2^2, ...)来计算新的哈希值,直到找到一个空位置为止。这种方法有助于避免哈希表中数据的聚集,提高哈希表的性能和数据的均匀分布。‌

 5.3.2 🌟开散列/哈希桶/开链法

开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。

拉链法解决冲突的特点:

  1. 将所有关键字为同义词的结点链接在同一个单链表中。
  2. 拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短。

即 数组+链表模式:

也就是说,开散列中每个桶中放的都是发生哈希冲突的元素。

HashMap采用的就是开散列法解决冲突。

但是当冲突严重时,链表的长度就会过于长,这样会影响搜索性能,

在Java中,当 数组长度超过64 && 链表长度超过8 ,链表就会转化为红黑树。

5.4 HashMap&HashSet

5.4.1 hashCode与equals方法

  • hashCode方法的作用是生成哈希值,通过哈希值计算出key在数组中的位置下标
  • equals方法的作用是判断,两个key的内容是否相等

例如:在使用put或者getValue方法时,通过hashCode找到元素的位置下标后,还需要使用equals方法一个一个的和链表中的元素比较,找到该元素在链表中的具体位置,若equals为true,说明找到了该元素。

故:当哈希表中的key为自定义类时,一定要重写equals和hashCode方法!!! 

注意:

  1. 若两个key通过equals比较结果为true,说明两个key的内容相同,说明通过hashCode得到的哈希值一定是相等的;
  2. 但是,若两个key 通过hashCode得到的哈希值相等,那么只能说明这两个key在数组中的位置是相同的,不能说明两个key的内容相同,也就是说equals可能为true也可能为flase。

总结:如果equals为true,那么hashCode出的哈希值一定相等; 如果hashCode出的哈希值相等,那么equals不一定为true!!!

5.5 性能分析

虽然哈希表一直在和冲突做斗争,但在实际使用过程中,我们认为哈希表的冲突率是不高的,冲突个数是可控的, 也就是每个桶中的链表的长度是一个常数,所以,通常意义下,我们认为哈希表的插入/删除/查找时间复杂度是 O(1) 。

5.6 总结

  1. HashMap 和 HashSet 即 java 中利用哈希表实现的 Map 和 Set
  2. HashMap 和 HashSet 中使用的是 哈希桶/开散列 方式解决冲突的
  3. java 会在冲突链表长度大于一定阈值后,将链表转变为搜索树(红黑树)
  4. java 中计算哈希值实际上是调用的类的 hashCode 方法,进行 key 的相等性比较是调用 key 的 equals 方法。所以如果要用自定义类作 HashMap 的key值或者 HashSet 的key值,必须重写 hashCode 和 equals 方法。
  5. equals 相等的对象,hashCode 一定是一致的。
  6. hashCode一致,equals不一定相等。
  7. HashMap和HashSet不涉及元素之间的比较,所以不用像TreeMap或TreeSet具备可比较功能。

相关文章:

数据结构(Java):Map集合Set集合哈希表

目录 1、介绍 1.1 Map和Set 1.2 模型 2、Map集合 2.1 Map集合说明 2.2 Map.Entry<K&#xff0c;V> 2.3 Map常用方法 2.4 Map注意事项及实现类 3、Set集合 3.1 Set集合说明 3.2 Set常用方法 3.3 Set注意事项及其实现类 4、TreeMap&TreeSet 4.1 集合类TreeM…...

网络战时代的国家安全:策略、技术和国际合作

网络战时代的国家安全涉及到策略、技术和国际合作等多个方面。以下是对这些问题的简要概述&#xff1a; 网络战策略 网络战策略是指在现代战争中&#xff0c;通过网络技术进行的信息收集、处理、分析、调度和指挥等一系列行动&#xff0c;旨在同时影响和干扰对方的网络系统&am…...

【elasticsearch实现优先展示连词并按某个字段折叠显示最新一条】

elasticsearch实现优先展示连词并按某个字段折叠显示最新一条 前言match_phrase 顺序前缀 boost 权重collapse 折叠基本用法高级功能排序 前言 场景要求&#xff1a; 优先展示关键词连词的商品按照某个字段折叠相同字段&#xff0c;并按指定排序字段选择第一个 match_phras…...

Golang | Leetcode Golang题解之第284题窥视迭代器

题目&#xff1a; 题解&#xff1a; type PeekingIterator struct {iter *Iterator_hasNext bool_next int }func Constructor(iter *Iterator) *PeekingIterator {return &PeekingIterator{iter, iter.hasNext(), iter.next()} }func (it *PeekingIterator) hasNe…...

C语言中的结构体

文章目录 前言一、结构体是什么&#xff1f;二、结构体的定义三、结构体的初始化四、结构体的嵌套五、结构体数组 1结构体数组的定义&#xff1a;六、结构体指针 一、结构体是什么&#xff1f; 我们知道一群类型相同的数据组合到一起是数组&#xff0c;那一群不同类型的数据组…...

3.qml与c++模块化开发

目录 模块化开发封装c模块并使用封装qml模块并使用 模块化开发 什么是模块化开发呢&#xff1f; 举个例子&#xff1a; 我们有一台台式电脑&#xff0c;我们台式电脑有显卡&#xff0c;内存&#xff0c;磁盘&#xff0c;cpu&#xff0c;键盘&#xff0c;鼠标等 你可以将这些部…...

怎么使用github上传XXX内所有文件

要将 目录中的所有文件上传到 GitHub&#xff0c;你可以按照以下步骤进行&#xff1a; 创建一个新的 GitHub 仓库 登录到你的 GitHub 账户。 点击右上角的加号&#xff08;&#xff09;&#xff0c;选择 “New repository”。 输入仓库名称&#xff08;例如&#xff1a;202407…...

合作伙伴中心Partner Center中添加了Copilot预览版

目录 一、引言 二、Copilot 功能概述 2.1 Copilot 简介 2.2 Copilot 的核心功能 2.3 Copilot 的访问和使用 三、Copilot 的使用方法 3.1 Copilot 功能区域 3.2 Copilot 使用示例 3.2.1 编写有效提示 3.2.2 使用反馈循环 四、负责任的人工智能 4.1 Copilot 结果的可…...

Navidrome音乐服务器 + 音流APP = 释放你的手机空间

20240727 By wdhuag 目录 前言&#xff1a; 参考&#xff1a; Navidrome音乐服务器 Demo试用&#xff1a; 支持多平台&#xff1a; 下载&#xff1a; 修改配置&#xff1a; 设置用NSSM成服务启动&#xff1a; 服务器本地访问网址&#xff1a; 音流 歌词封面API&am…...

Prometheus安装部署

文章目录 1.Prometheus(普罗米修斯)安装部署1.1部署环境准备1.2部署prometheus1.3主机数据展示 2.Grafana安装部署2.1部署Grafana2.2配置Grafana数据源2.2配置Grafana仪表板 3.AlertManager安装部署3.1部署alertmanager3.2告警邮件发送配置3.3测试邮件告警效果3.4自定义邮件告警…...

算法(查找算法---二分查找/索引查找/哈希表查找)

二、查找算法 什么是查找算法&#xff1a; 在一个数据序列中&#xff0c;查找某个数据是否存在或存在的位置&#xff0c;在实际开发过程中使用的频率非常高&#xff0c;例如对数据常见的操作有增、删、改、查&#xff0c;增加数据时需要查询新增加的数据是否重复&#xff0c;…...

SQL labs-SQL注入(二)

环境搭建参考 SQL注入&#xff08;一&#xff09; 一&#xff0c;SQL labs-less2。 http://192.168.61.206:8001/Less-2/?id-1 union select 1,2,group_concat(username , password) from users-- 与第一关没什么太大的不同&#xff0c;唯一区别就是闭合方式为数字型。 二…...

go 语言踏出第一步

1、下载Go语言安装包&#xff1a;在官方网站&#xff08;https://golang.org/dl/&#xff09;上下载适合你操作系统的Go语言安装包。选择一个tar.gz格式的包。 2、解压安装包&#xff1a;打开终端&#xff0c;进入下载目录&#xff0c;并使用以下命令解压安装包&#xff1a; ta…...

SpringBoot-21 SpringBoot微服务的发布与部署(3种方式)

基于 SpringBoot 的微服务开发完成之后&#xff0c;现在到了把它们发布并部署到相应的环境去运行的时候了。 SpringBoot 框架只提供了一套基于可执行 jar 包&#xff08;executable jar&#xff09;格式的标准发布形式&#xff0c;但并没有对部署做过多的界定&#xff0c;而且为…...

在occluded Person Re-ID中,选择clip还是ViT作为backbone?

在遮挡行人再识别&#xff08;Occluded Person Re-Identification, Occluded Person Re-ID&#xff09;任务中&#xff0c;使用CLIP&#xff08;Contrastive Language-Image Pre-Training&#xff09;作为backbone和使用Vision Transformer&#xff08;ViT&#xff09;作为back…...

Linuxnat网络配置

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ☁️运维工程师的职责&#xff1a;监…...

77.WEB渗透测试-信息收集-框架组件识别利用(1)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;76.WEB渗透测试-信息收集- WAF、框架组件识别&#xff08;16&#xff09; java&#xff…...

ExcelJS:轻松实现Excel文件的读取、操作与写入

文章目录 发现宝藏1. 简介2. 安装3. 创建工作簿4. 设置工作簿属性5. 添加工作表6.删除工作表7.访问工作表8. 列操作9. 行操作10. 单元格操作 发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【宝…...

Java 多线程技术详解

文章目录 Java 多线程技术详解目录引言多线程的概念为什么使用多线程&#xff1f;多线程的特征多线程的挑战 多线程的实现方式3.1 继承 Thread 类示例代码&#xff1a; 3.2 实现 Runnable 接口示例代码&#xff1a; 3.3 使用 Executor 框架示例代码&#xff1a; 3.4 使用 Calla…...

一份简单实用的MATLAB M语言编码风格指南

MATLAB M语言编码风格指南 1. 文件命名2. 函数命名3. 注释4. 变量命名5. 布局、注释和文档6. 代码结构7. 错误处理8. 性能优化9. 格式化输出 MATLAB M文件的编码规范对于确保代码的可读性、可维护性和一致性非常重要。下面是一份MATLAB M语言编码规范的建议&#xff0c;可以作为…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...