深入解析 Java Stream API:筛选子节点的优雅实现!!!
🚀 深入解析 Java Stream API:筛选子节点的优雅实现 🔧
大家好!👋 今天我们来聊聊 Java 8 中一个非常常见的操作:使用 Stream API 从 Map
中筛选出特定条件的元素。🎉 具体来说,我们将深入分析以下代码片段:
List<InviteCode> children = inviteCodeMap.values().stream().filter(ic -> Objects.equals(ic.getCreatedBy(), root.getId())).collect(Collectors.toList());
这段代码是构建邀请码层级树的一部分,背后涉及了 Stream API、Lambda 表达式以及 Collectors.toList
的强大功能。💡 我们将从代码的背景开始,逐步拆解它的实现原理,探讨使用场景、优势和优化方法,最后通过一个实际案例展示它的应用。为了更直观地理解整个过程,我们还会插入一个 Mermaid 流程图!📊
准备好了吗?让我们开始吧!🚀
📖 背景:为什么需要筛选子节点?
在 Java 开发中,我们经常需要处理层级数据。例如,在一个邀请码系统中,我们有一个 Map<Integer, InviteCode>
,其中 InviteCode
是一个实体类,包含以下字段:
public class InviteCode {private Integer id;private String inviteCode;private Integer inviteLevel;private Integer createdBy;// Getters and Setterspublic Integer getId() {return id;}public String getInviteCode() {return inviteCode;}public Integer getInviteLevel() {return inviteLevel;}public Integer getCreatedBy() {return createdBy;}
}
假设我们有一个 Map<Integer, InviteCode>
(inviteCodeMap
),包含 adminId = 7
的所有邀请码记录:
id | admin_id | created_by | invite_code | invite_level |
---|---|---|---|---|
20 | 7 | NULL | ****** | 0 |
21 | 7 | 20 | 263113 | 1 |
22 | 7 | 20 | 704358 | 1 |
23 | 7 | 20 | 982868 | 1 |
24 | 7 | NULL | ****** | 0 |
25 | 7 | 24 | ****** | 1 |
26 | 7 | 25 | ****** | 2 |
27 | 7 | 26 | 991476 | 3 |
我们的目标是构建一个以 adminId
为根的邀请码层级树。层级树的构建需要递归地从根节点开始,找到每个节点的子节点。子节点的定义是 createdBy
等于当前节点 id
的 InviteCode
对象。换句话说:
createdBy == root.getId()
:表示这是一个子节点(root
是它的父节点)。createdBy != root.getId()
:表示这不是root
的子节点。
因此,我们需要从 inviteCodeMap
中筛选出所有 createdBy == root.getId()
的 InviteCode
对象,这就是以下代码的作用:
List<InviteCode> children = inviteCodeMap.values().stream().filter(ic -> Objects.equals(ic.getCreatedBy(), root.getId())).collect(Collectors.toList());
🌟 代码拆解:一步步理解
让我们逐步拆解这段代码,弄清楚它是如何工作的!
1. inviteCodeMap.values()
inviteCodeMap
:是一个Map<Integer, InviteCode>
,键是InviteCode
的id
,值是InviteCode
对象本身。values()
:Map
的方法,返回Map
中所有值的Collection
(类型为Collection<InviteCode>
)。- 在这里,
inviteCodeMap.values()
返回一个包含所有InviteCode
对象的集合(例如id = 20, 21, ..., 27
的 8 个对象)。
- 在这里,
结果:inviteCodeMap.values()
是一个 Collection<InviteCode>
,包含所有 InviteCode
对象。
2. .stream()
stream()
:将Collection<InviteCode>
转换为一个Stream<InviteCode>
。Stream
是 Java 8 引入的流式 API,允许你以声明式的方式处理集合数据(例如映射、过滤、归约等)。
结果:inviteCodeMap.values().stream()
生成了一个 Stream<InviteCode>
,包含 inviteCodeMap
中的所有 InviteCode
对象。
3. .filter(ic -> Objects.equals(ic.getCreatedBy(), root.getId()))
filter
:是 Stream API 的一个中间操作,用于筛选流中的元素。ic -> Objects.equals(ic.getCreatedBy(), root.getId())
:这是一个 Lambda 表达式,表示一个谓词(Predicate),用于判断每个InviteCode
对象是否满足条件。ic
:代表流中的每个InviteCode
对象。ic.getCreatedBy()
:获取InviteCode
对象的createdBy
字段(Integer
类型)。root.getId()
:获取当前根节点的id
(Integer
类型)。Objects.equals(ic.getCreatedBy(), root.getId())
:比较ic.getCreatedBy()
和root.getId()
是否相等。- 使用
Objects.equals
而不是直接==
是为了安全地处理null
值(如果ic.getCreatedBy()
为null
,==
可能会导致问题)。
- 使用
- 作用:
filter
会保留所有满足条件的元素(createdBy
等于root.getId()
的InviteCode
),丢弃不满足条件的元素。
类型:Predicate<InviteCode>
,将 InviteCode
映射为一个布尔值(true
或 false
)。
4. .collect(Collectors.toList())
collect
:是 Stream API 的终止操作,用于将流中的元素收集到一个结果容器中(例如List
、Set
或Map
)。Collectors.toList()
:是一个收集器(Collector),专门用于将流中的元素收集到一个List
中。
结果:collect(Collectors.toList())
将筛选后的 Stream<InviteCode>
收集到一个新的 List<InviteCode>
中。
5. 整体效果
inviteCodeMap.values().stream().filter(ic -> Objects.equals(ic.getCreatedBy(), root.getId())).collect(Collectors.toList())
:- 从
inviteCodeMap
获取所有InviteCode
对象,转换为Stream<InviteCode>
。 - 筛选出
createdBy
等于root.getId()
的InviteCode
对象(即root
的子节点)。 - 将筛选结果收集到一个新的
List<InviteCode>
中。
- 从
- 赋值:将结果赋值给
children
,children
是一个List<InviteCode>
,包含root
的所有直接子节点。
📊 Mermaid 流程图:可视化筛选过程
为了更直观地理解从 Map<Integer, InviteCode>
筛选子节点的过程,我们使用 Mermaid 流程图来展示:
- 流程说明:
- 从
Map<Integer, InviteCode>
开始,获取所有值(inviteCodeMap.values()
)。 - 转换为
Stream<InviteCode>
。 - 对流中的每个
InviteCode
对象:- 检查
createdBy == root.getId()
。 - 如果
true
,保留该对象;如果false
,丢弃。
- 检查
- 将筛选后的元素收集到
List<InviteCode>
中。
- 从
📝 示例:具体数据
假设 inviteCodeMap
包含以下数据(adminId = 7
):
id | admin_id | created_by | invite_code | invite_level |
---|---|---|---|---|
20 | 7 | NULL | ****** | 0 |
21 | 7 | 20 | 263113 | 1 |
22 | 7 | 20 | 704358 | 1 |
23 | 7 | 20 | 982868 | 1 |
24 | 7 | NULL | ****** | 0 |
25 | 7 | 24 | ****** | 1 |
26 | 7 | 25 | ****** | 2 |
27 | 7 | 26 | 991476 | 3 |
1. inviteCodeMap.values().stream()
inviteCodeMap.values()
返回一个Collection<InviteCode>
,包含 8 个InviteCode
对象(id = 20, 21, ..., 27
)。.stream()
将其转换为Stream<InviteCode>
。
2. .filter(ic -> Objects.equals(ic.getCreatedBy(), root.getId()))
假设当前 root
是 id = 20
的 InviteCode
:
root.getId() = 20
。- 对每个
InviteCode
对象检查createdBy
是否等于20
:id = 20
:createdBy = null
,Objects.equals(null, 20) = false
,丢弃。id = 21
:createdBy = 20
,Objects.equals(20, 20) = true
,保留。id = 22
:createdBy = 20
,Objects.equals(20, 20) = true
,保留。id = 23
:createdBy = 20
,Objects.equals(20, 20) = true
,保留。id = 24
:createdBy = null
,Objects.equals(null, 20) = false
,丢弃。id = 25
:createdBy = 24
,Objects.equals(24, 20) = false
,丢弃。id = 26
:createdBy = 25
,Objects.equals(25, 20) = false
,丢弃。id = 27
:createdBy = 26
,Objects.equals(26, 20) = false
,丢弃。
结果:筛选后的 Stream<InviteCode>
包含 3 个元素:
InviteCode(id=21, createdBy=20, ...)
。InviteCode(id=22, createdBy=20, ...)
。InviteCode(id=23, createdBy=20, ...)
。
3. .collect(Collectors.toList())
- 将筛选后的
Stream<InviteCode>
收集到一个新的List<InviteCode>
中。
结果:children
是一个 List<InviteCode>
,包含以下 3 个元素:
InviteCode(id=21, createdBy=20, ...)
。InviteCode(id=22, createdBy=20, ...)
。InviteCode(id=23, createdBy=20, ...)
。
4. 另一个例子:root = id = 24
root.getId() = 24
。- 筛选
createdBy = 24
:id = 20
:createdBy = null
,丢弃。id = 21
:createdBy = 20
,丢弃。id = 22
:createdBy = 20
,丢弃。id = 23
:createdBy = 20
,丢弃。id = 24
:createdBy = null
,丢弃。id = 25
:createdBy = 24
,保留。id = 26
:createdBy = 25
,丢弃。id = 27
:createdBy = 26
,丢弃。
结果:children
包含 1 个元素:
InviteCode(id=25, createdBy=24, ...)
。
🌟 为什么需要 children
?
在 buildTree
方法中,children
的作用是找到当前节点(root
)的所有直接子节点,以便递归构建树形结构:
private InviteCodeTreeDTO buildTree(InviteCode root, Map<Integer, InviteCode> inviteCodeMap) {InviteCodeTreeDTO node = new InviteCodeTreeDTO();node.setId(root.getId());node.setInviteCode(root.getInviteCode());node.setInviteLevel(root.getInviteLevel());node.setChildren(new ArrayList<>());// 查找所有子节点(createdBy = root.id)List<InviteCode> children = inviteCodeMap.values().stream().filter(ic -> Objects.equals(ic.getCreatedBy(), root.getId())).collect(Collectors.toList());// 递归构建子树for (InviteCode child : children) {InviteCodeTreeDTO childNode = buildTree(child, inviteCodeMap);node.getChildren().add(childNode);}return node;
}
- 层级树构建:
- 当前节点
root
(例如id = 20
)。 - 找到所有子节点(
createdBy = 20
的InviteCode
,即id = 21, 22, 23
)。 - 递归调用
buildTree
为每个子节点构建子树。
- 当前节点
- 递归:通过不断查找子节点,构建完整的树形结构。
🚀 优势:为什么使用 Stream API?
1. 代码简洁
- Stream API 提供了声明式的写法,比传统的
for
循环更简洁。 - 传统写法可能需要手动遍历和填充
List
:List<InviteCode> children = new ArrayList<>(); for (InviteCode ic : inviteCodeMap.values()) {if (Objects.equals(ic.getCreatedBy(), root.getId())) {children.add(ic);} }
- 使用 Stream API,代码更简洁优雅。
2. 功能强大
- Stream API 支持链式操作,可以轻松添加其他过滤条件。
- 例如,如果只想筛选
inviteLevel == 1
的子节点:List<InviteCode> children = inviteCodeMap.values().stream().filter(ic -> Objects.equals(ic.getCreatedBy(), root.getId()) && ic.getInviteLevel() == 1).collect(Collectors.toList());
3. 并行处理
- Stream API 支持并行处理(
parallelStream()
),在大规模数据下可以提高性能:List<InviteCode> children = inviteCodeMap.values().parallelStream().filter(ic -> Objects.equals(ic.getCreatedBy(), root.getId())).collect(Collectors.toList());
🛠️ 优化建议
1. 更高效的子节点查找
当前实现中,inviteCodeMap.values().stream()
需要遍历所有 InviteCode
对象,效率不高。可以通过预先构建一个 Map<Integer, List<InviteCode>>
来存储 createdBy
到子节点的映射:
// 在 getAdminInviteCodeTree 中预构建
Map<Integer, List<InviteCode>> childrenMap = inviteCodes.stream().filter(ic -> ic.getCreatedBy() != null).collect(Collectors.groupingBy(InviteCode::getCreatedBy));// 修改 buildTree 方法
private InviteCodeTreeDTO buildTree(InviteCode root, Map<Integer, InviteCode> inviteCodeMap, Map<Integer, List<InviteCode>> childrenMap) {InviteCodeTreeDTO node = new InviteCodeTreeDTO();node.setId(root.getId());node.setInviteCode(root.getInviteCode());node.setInviteLevel(root.getInviteLevel());node.setChildren(new ArrayList<>());// 直接从 childrenMap 获取子节点List<InviteCode> children = childrenMap.getOrDefault(root.getId(), Collections.emptyList());for (InviteCode child : children) {InviteCodeTreeDTO childNode = buildTree(child, inviteCodeMap, childrenMap);node.getChildren().add(childNode);}return node;
}
- 效果:通过
childrenMap
,可以以O(1)
的时间复杂度找到某个id
的所有子节点。
2. 并row处理
如果 inviteCodeMap
非常大,可以使用 parallelStream()
提高性能:
List<InviteCode> children = inviteCodeMap.values().parallelStream().filter(ic -> Objects.equals(ic.getCreatedBy(), root.getId())).collect(Collectors.toList());
- 注意:并行流适合大数据量,但在小数据量下可能有性能开销。
3. 日志记录
添加日志,跟踪子节点的查找:
List<InviteCode> children = inviteCodeMap.values().stream().filter(ic -> Objects.equals(ic.getCreatedBy(), root.getId())).collect(Collectors.toList());
logger.info("Found {} children for root node {}: {}", children.size(), root.getId(), children);
- 效果:便于调试和监控。
📝 完整代码:实际应用
以下是完整的 InviteCodeService
实现,展示了如何使用 children
构建层级树:
public class InviteCodeService {private final InviteCodeRepository inviteCodeRepository;private static final Logger logger = LoggerFactory.getLogger(InviteCodeService.class);public InviteCodeService(InviteCodeRepository inviteCodeRepository) {this.inviteCodeRepository = inviteCodeRepository;}public AdminInviteCodeTreeDTO getAdminInviteCodeTree(Integer adminId) {List<InviteCode> inviteCodes = inviteCodeRepository.findByAdminId(adminId);if (inviteCodes.isEmpty()) {AdminInviteCodeTreeDTO result = new AdminInviteCodeTreeDTO();result.setAdminId(adminId);result.setChildren(Collections.emptyList());return result;}// 将 List<InviteCode> 转换为 Map<Integer, InviteCode>Map<Integer, InviteCode> inviteCodeMap = inviteCodes.stream().collect(Collectors.toMap(InviteCode::getId, ic -> ic));// 预构建 createdBy 到子节点的映射Map<Integer, List<InviteCode>> childrenMap = inviteCodes.stream().filter(ic -> ic.getCreatedBy() != null).collect(Collectors.groupingBy(InviteCode::getCreatedBy));// 找到所有根节点(createdBy = NULL)List<InviteCode> roots = inviteCodes.stream().filter(ic -> ic.getCreatedBy() == null).collect(Collectors.toList());logger.info("Found {} root nodes for adminId {}: {}", roots.size(), adminId, roots);// 如果没有根节点,直接返回if (roots.isEmpty()) {AdminInviteCodeTreeDTO result = new AdminInviteCodeTreeDTO();result.setAdminId(adminId);result.setChildren(Collections.emptyList());return result;}// 为每个根节点构建树形结构List<InviteCodeTreeDTO> trees = new ArrayList<>();for (InviteCode root : roots) {InviteCodeTreeDTO tree = buildTree(root, inviteCodeMap, childrenMap);trees.add(tree);}AdminInviteCodeTreeDTO result = new AdminInviteCodeTreeDTO();result.setAdminId(adminId);result.setChildren(trees);return result;}private InviteCodeTreeDTO buildTree(InviteCode root, Map<Integer, InviteCode> inviteCodeMap, Map<Integer, List<InviteCode>> childrenMap) {InviteCodeTreeDTO node = new InviteCodeTreeDTO();node.setId(root.getId());node.setInviteCode(root.getInviteCode());node.setInviteLevel(root.getInviteLevel());node.setChildren(new ArrayList<>());// 直接从 childrenMap 获取子节点List<InviteCode> children = childrenMap.getOrDefault(root.getId(), Collections.emptyList());logger.info("Found {} children for root node {}: {}", children.size(), root.getId(), children);for (InviteCode child : children) {InviteCodeTreeDTO childNode = buildTree(child, inviteCodeMap, childrenMap);node.getChildren().add(childNode);}return node;}
}
🎉 总结
通过 Stream API 和 Collectors.toList
,我们可以轻松地从 Map<Integer, InviteCode>
中筛选出子节点,为后续的层级树构建提供了基础。💻
- 核心代码:
inviteCodeMap.values().stream().filter(ic -> Objects.equals(ic.getCreatedBy(), root.getId())).collect(Collectors.toList())
筛选出子节点。 - 优势:代码简洁、功能强大、支持并行处理。
- 优化:通过
childrenMap
提高查找效率、添加日志、支持并行流。
希望这篇博客对你理解 Stream API 和 filter
操作有所帮助!💬 如果你有其他问题,欢迎留言讨论!🚀
📚 参考:Java 官方文档、Collectors
源码。点赞和分享哦!😊
相关文章:
深入解析 Java Stream API:筛选子节点的优雅实现!!!
🚀 深入解析 Java Stream API:筛选子节点的优雅实现 🔧 大家好!👋 今天我们来聊聊 Java 8 中一个非常常见的操作:使用 Stream API 从 Map 中筛选出特定条件的元素。🎉 具体来说,我们…...
Vala编程语言教程-面向对象编程语基础
基础 尽管Vala语言并不强制你使用对象进行编程,但有些功能只能通过对象的方式来实现。因此,在大多数情况下,你肯定会希望采用面向对象的编程风格。与大多数当前的编程语言一样,为了定义你自己的对象类型,你需要编写一个…...
写读后感的时候,可以适当地引用书中的内容吗?
写读后感时,适当地引用书中的内容是可以的,这样可以更好地支持你的观点和感受,增强文章的可信度和说服力。 引用书中的内容可以帮助读者更好地理解你所讨论的主题和人物,同时也可以展示你对原著的深入理解和阅读能力。但是&#…...
计算机网络高频(二)TCP/IP基础
计算机网络高频(二)TCP/IP基础 1.什么是TCP/IP⭐⭐ TCP/IP是一种网络通信协议,它是互联网中最常用的协议之一。TCP/IP有两个基本的协议:TCP(传输控制协议)和IP(互联网协议)。 TCP(Transmission Control Protocol,传输控制协议)是一种可靠的、面向连接的协议。它负…...
蓝桥杯 之 数论
文章目录 习题质数找素数 LCM报数游戏 快速幂数字诗意 组合数与错位排序小蓝与钥匙 同余取模 数论,就是一些数学问题,蓝桥杯十分喜欢考察,常见的数论的问题有:取模,同余,大整数分解,素数&#x…...
无法写入文件:(FileSystemError): Error: EPERM: operation not permitted, open...)
问题分析: 当我想在Visual Studio Code中编写文件时,出现无法写入文件的错误,发现是权限的问题 解决办法: 右键应用图标 → 以管理员身份运行就可以了...
Java爬虫抓取B站视频信息
依赖 <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.17.2</version> <!-- 最新版可去官网查看 --></dependency>编码 public static List<VideoDto> parseSearchPage(Str…...
Sql Server数据迁移易错的地方
背景:之前一直台式机,毕业准备答辩了,要将代码搬到笔记本运行才方便些。这个Sql数据弄过来搞了好几个小时 还原备份报错:媒体簇的结构不正确。SQL Server 无法处理此媒体簇。 解决:升级到sql server版本比备份的那个高…...
七、服务器远程桌面报错
🌻🌻目录🌻🌻 一、远程桌面报错-用户账户限制(例如,时间限制)会阻止你登录。 一、远程桌面报错-用户账户限制(例如,时间限制)会阻止你登录。 原因是被远程的系…...
JAVA 之「优先队列」:大顶堆与小顶堆的实现与应用
Java 优先队列:大顶堆与小顶堆的实现与应用 文章目录 Java 优先队列:大顶堆与小顶堆的实现与应用一、什么是优先队列和堆?1. 优先队列2. 堆 二、Java PriorityQueue 基本用法1. 默认小顶堆示例代码输出 2. 实现大顶堆示例代码输出 三、大顶堆…...
压缩壳学习
壳是什么 壳就是软件的一个保护套,防止软件被进行反编译或被轻易地修改。 其作用就是为了保护软件。 常见的大类壳有压缩壳、加密壳、VM 壳的分类。 压缩壳顾名思义就是用来减小软件的文件大小的;加密壳,通过加密软件来保护软件ÿ…...
VRRP配置双出口ipsec隧道建立。
背景:在做毕设时,发现规划的不是那么合理,vrrp主备切换后,ipsec隧道并没有跟着切换到与备防火墙建立隧道,这是因为配置了双出口,路由的设计导致vrrp主备切换ipsec隧道没有跟着切换。 fw1为主,fw…...
机器学习——Numpy的神奇索引与布尔索引
在 NumPy 中,神奇索引(Fancy Indexing) 和 布尔索引(Boolean Indexing) 是两种强大的索引方式,用于从数组中提取特定元素或子集。以下是它们的详细说明和示例: 1. 神奇索引(Fancy In…...
Linux:进程间通信
文章目录 前言一、进程间通信介绍1.1 进程间通信的目的1.2 进程间通信的发展与分类 二、管道2.1 匿名管道原理2.2 通信管道会出现的情况和特性(重要)2.3 命名管道2.3.1 命名管道与匿名管道的区别 三、system V3.1 共享内存原理3.2 键值3.2.1 键值生成原理…...
Mysql配套测试之查询篇
🏝️专栏:Mysql_猫咪-9527的博客-CSDN博客 🌅主页:猫咪-9527-CSDN博客 “欲穷千里目,更上一层楼。会当凌绝顶,一览众山小。” 目录 条件查询简单测试: 1.查询英语成绩不及格的同学(<60) 2…...
基于SSM框架的汽车租赁平台(源码+lw+部署文档+讲解),源码可白嫖!
摘要 时代在飞速进步,每个行业都在努力发展现在先进技术,通过这些先进的技术来提高自己的水平和优势,汽车租赁平台当然不能排除在外。汽车租赁平台是在实际应用和软件工程的开发原理之上,运用Java语言以及SSM框架进行开发&#x…...
常考计算机操作系统面试习题(三下)
20. 请求页式存储管理系统缺页率计算 题目: 假设一个作业的页面走向为 1、2、3、4、1、2、5、1、2、3、4、5,当分配给该作业的物理块数分别为 3 和 4 时,计算采用下述页面置换算法的缺页率: (1) 先进先出(FIFO&…...
Spring IOC核心详解:掌握控制反转与依赖注入
文章目录 前言一、IOC核心思想二、IOC容器实现1.核心接口:2.XML配置范例 三、Bean管理实践1.创建对象(1)基于xml方式创建对象(2)用注解的方式创建对象 2.依赖注入(1)基于xml方式注入属性基础类型…...
Servlet、HttpServletRequest、HttpServletResponse、静态与动态网页、jsp、重定向与转发
DAY15.2 Java核心基础 JavaWeb 要想通过浏览器或者客户端来访问java程序,必须通过Servlet来处理 没有Servlet,java是无法处理web请求的 Web交互: 接收请求HttpServletRequest:可以获取到请求的信息,比如uri&#…...
Linux 内核源码阅读——ipv4
Linux 内核源码阅读——ipv4 综述 在 Linux 内核中,IPv4 协议的实现主要分布在 net/ipv4/ 目录下。以下是一些关键的源文件及其作用: 1. 协议栈核心 net/ipv4/ip_input.c:处理接收到的 IPv4 数据包(输入路径)。net…...
组合总和 II:去重逻辑深度解析
组合总和 II:去重逻辑深度解析 在算法中,解决“组合总和 II”这类问题时,去重往往是最具挑战性的一环。如何避免重复组合,同时保证所有组合的唯一性,是实现高效算法的关键。今天,我们就来深度解析组合总和…...
蓝桥杯备考:二分答案之路标设置
最大距离,找最小空旷指数值,我们是很容易想到用二分的,我们再看看这个答案有没有二段性 是有这么个二段性的,我们只要二分就行了,但是二分的check函数是有点不好想的,我们枚举空旷值的时候,为了…...
[HY000][1366] Incorrect string value: ‘å¼ ä¸‘ for column ‘name‘ at row 1
常见原因 字符集不兼容 插入的数据包含当前字符集(如 latin1)不支持的特殊字符(如中文、Emoji 等)。 表、列或连接的字符集未正确配置为支持目标字符(如未使用 utf8mb4)。 客户端/服务端编码不一致 客户…...
什么是C++对象之间的view proxies
在C中,view proxies 是一种轻量级的对象,用于提供对另一个对象的间接访问或视图,而不直接拥有或管理该对象的数据。它们通常用于简化对复杂数据结构的访问,或在不需要复制数据的情况下提供特定的视图。 1. View Proxies 的核心概…...
MyBatis参数赋值技巧:#{} 和 ${} 的区别与实践
目录 一、前言二、 #{} 和${} 的使用方法和区别2.1 #{}使用方法2.2 ${}使用方法2.3#{} 和 ${} 的主要区别2.4使用建议 三、总结 一、前言 在 MyBatis 中,#{} 和 ${} 都用于在 SQL 语句中绑定参数,但它们在具体实现和安全性方面有所不同。理解它们的区别…...
5-1 使用ECharts将MySQL数据库中的数据可视化
方法一:使用Python Flask框架搭建API 对于技术小白来说,使用ECharts将MySQL数据库中的数据可视化需要分步骤完成。以下是详细的实现流程: 一、技术架构 后端服务:使用Python Flask框架搭建API(简单易学ÿ…...
协程的调度的对称与非对称
下图表示的就是对称协程,进入到该协程之后只能有一个操作就是yield,把cpu让回给调度器; 下图表示非对称协议,可以有两个操作,就是resume和yield,从哪里resume的,yield就会回到该位子;...
C# 中比较实用的关键字,基础高频面试题!
前言 在C#编程中关键字是构建逻辑和实现功能的基石,它承载着编程语言的语法规则和编程智慧。熟练掌握这些基础高频关键字对提升编程能力和面试表现至关重要,它们是日常开发和解决复杂问题的关键。 DotNetGuide 全面的C#/.NET/.NET Core学习、工作、面试指…...
文献分享: XTR——优化Token级检索的高效多向量模型
原文章 文章目录 1. XTR \textbf{1. XTR} 1. XTR原理 1.1. \textbf{1.1. } 1.1. 导论 1.2. XTR \textbf{1.2. XTR} 1.2. XTR的训练和推理 2. \textbf{2. } 2. 实验与分析 2.1. \textbf{2.1. } 2.1. 实验配置与结果 2.2. \textbf{2.2. } 2.2. 结果分析 3. \textbf{3. } 3. 其它分…...
【数据结构】C语言实现树和森林的遍历
C语言实现树和森林的遍历 导读一、树的遍历二、森林的遍历2.1 为什么森林没有后序遍历?2.2 森林中存不存在层序遍历?三、C语言实现3.1 准备工作3.2 数据结构的选择3.3 树与森林的创建3.4 树与森林的遍历3.4.1 先根遍历3.4.2 后根遍历3.4.3 森林的遍历3.5 树与森林的销毁3.6 算…...
《Python深度学习》第七讲:生成式深度学习
在深度学习的世界里,生成式模型是一种非常有趣且富有创造力的技术。它们能够生成全新的内容,比如文本、图像、音乐等,甚至可以创造出从未见过的虚拟世界。这一讲,我们将深入探讨生成式深度学习的核心技术,包括 LSTM 文本生成、DeepDream、神经风格迁移、变分自编码器(VAE…...
Spring的IOC
在现代 Java 开发中,Spring 框架几乎无处不在,特别是其核心的 IOC(Inversion of Control) 容器,几乎所有Spring的功能都与它紧密相关。 一、什么是IOC IOC,全称为 Inversion of Control(控制反…...
常考计算机操作系统面试习题(四)
目录 1. Peterson 算法伪代码 2. 信号量生产者消费者问题分析 3. 注释 Peterson 主函数并分析输出结果 4. 用 fork 创建子进程的程序 1. Peterson 算法伪代码 题目: 写出 Peterson 算法的伪代码。 参考答案: // 定义变量 boolean flag[2]; //…...
Visual Studio Code 连接 SAP ERP 系统
首先确保服务打开 在vscode,在extension安装ABAP remote filesystem,然后打开设置SAP 系统的地址配置 CtrlshiftP 执行代码:AbapFS connect to an ABAP system,可以根据要求一步一步配置。 根据配置。加载系统 也可以直接在extens…...
从报错到成功:Mermaid 流程图语法避坑指南✨
🚀 从报错到成功:Mermaid 流程图语法避坑指南 🚀 🚨 问题背景 在开发文档或技术博客中,我们经常使用 Mermaid 流程图 来可视化代码逻辑。但最近我在尝试绘制一个 Java Stream 转换流程图时,遭遇了以下报错…...
TDengine 中的 show 命令
简介 SHOW 命令可以用来获取简要的系统信息。若想获取系统中详细的各种元数据、系统信息和状态,请使用 select 语句查询 INFORMATION_SCHEMA 数据库中的表, 详见 元数据查询 SHOW APPS SHOW APPS;显示接入集群的应用(客户端)信息。 SHOW …...
博弈论中的均衡精炼:完美贝叶斯均衡、序贯均衡与颤抖手均衡详解
博弈论中的均衡精炼:完美贝叶斯均衡、序贯均衡与颤抖手均衡详解 1. 引言:为什么需要均衡精炼? 在博弈论中,纳什均衡是分析策略互动的核心工具,但其存在一个显著缺陷:无法排除不合理的均衡。例如࿰…...
github代理 | 快速clone项目
代理网址: https://ghproxy.com/ https://ghproxy.com/代理网址: https://ghproxy.com/ 比如需要克隆的项目git地址为:https://github.com/AUTOMATIC1111/stable-diffusion-webui.git git clone https://ghproxy.com/https://github.com/AUTO…...
C语言基础与进阶学习指南(附运行效果图及术语解析)
C语言基础与进阶学习指南(附运行效果图及术语解析) 目录 C语言标准与编译流程CPU与内存基础C语言基础语法数据类型详解变量与内存管理运算符与表达式输入输出函数函数与内存管理指针与内存操作结构体与高级应用 1. C语言标准与编译流程 1.1 C语言标准演…...
【Scrapy】Scrapy教程8——处理子链接
通过前面几篇文章,已经了解了如何去爬取网页内容并存储到数据库,但是目前只是存储了一个页面的内容,现在想要获取每篇文章链接内的文章内容,我们来看看怎么获取。 生成新请求 首先我们肯定要先拿到链接,所以第一步都获取文章标题和链接肯定少不了,然后再爬取获取到到子…...
Python推导式深入解析
引言 Python 以其简洁、高效的语法而备受开发者喜爱,其中推导式(Comprehensions)更是 Python 语法的一大特色。推导式提供了一种简洁明了的方式来创建列表、集合和字典等数据结构,让代码更加紧凑和易读。本文将深入探讨 Python 推…...
在 macOS 上配置 SSH 连接 GitHub
在 macOS 上使用 SSH 连接 GitHub,可以免去每次使用 Git 时输入密码的麻烦,提高开发效率。本文将介绍如何在 macOS 上生成 SSH 密钥并配置 GitHub 进行身份认证。 1. 检查是否已有 SSH 密钥 在终端运行以下命令,检查是否已有 SSH 密钥&#…...
常考计算机操作系统面试习题(二)(中)
目录 24. 操作系统的主要功能有哪些? 25. 文件的属性主要有哪些? 26. 对文件的基本操作主要有哪些? 27. 目录的基本操作有哪些? 28. 目录的逻辑结构有哪些种? 29. 简述银行家算法的Available、Max、Allocation、…...
手机录视频风噪太大?华为Pura X“AI降风噪“太硬核了
你是否也在用手机录像时,比如大海海浪、阅览群山、空旷的原野的时候,呼啸的风总是能沦为刺耳的噪音,让精心构思的镜头,最后因为呼啸的风声最终成为“灾难现场”。传统的解决方式往往陷入两难:物理防风罩影响收音指向性…...
React 事件处理
1. React 事件处理的基本概念 React 事件处理的特点: 驼峰命名法:事件名采用驼峰命名法,如 onClick、onChange。JSX 语法:事件处理函数通过 JSX 传递给元素,如 <button onClick{handleClick}>。合成事件&#…...
搭建React简单项目
一、项目构建 目录结构: 安装脚手架 npm install -g create-react-app // or yarn add -g create-react-app 一、项目版本 1、react:"^18.3.1"; 2、react-router-dom:"^6.23.1"; 3、项目创…...
ROCK 280A-M 工业级电调:高性能无人机动力心脏,重塑严苛场景飞行边界
—— 工业级动力控制系统解决方案 —— 【产品概述】 针对工业级无人机高负载、复杂工况需求,南昌长空科技的ROCK 280A-M 电调以航空级标准打造动力控制中枢。采用工业级控制算法与智能自适应系统,为多旋翼 / 固定翼无人机提供稳定动力支撑,突…...
带你从入门到精通——自然语言处理(十. BERT)
建议先阅读我之前的博客,掌握一定的自然语言处理前置知识后再阅读本文,链接如下: 带你从入门到精通——自然语言处理(一. 文本的基本预处理方法和张量表示)-CSDN博客 带你从入门到精通——自然语言处理(二…...
八股JAVA并发
多线程 线程的创建方式有哪些? 1.继承Thread类 2.实现Runnable接口 3.Callable接口FutureTask 4.线程池 1.继承Thread类 这是最直接的一种方式,用户自定义类继承java.lang.Thread类,重写其run()方法,run()方法中定义了线程执行的具体任务。…...
#include <hello.h> 与 #include “hello.h“的区别
#include <hello.h> 和 #include "hello.h" 在C/C中用于包含头文件,但它们在搜索头文件时的行为有所不同,这可能导致前者找不到头文件的情况。 ### 区别 1. **搜索路径不同** - #include "hello.h":编译器首先…...