C++中map和set的封装
一、关于封装过程中传入的模板参数的问题
通过源码中的封装方式进行理解:
1.1map和set中成员变量
set中:
template <class Key, class Compare = less<Key>, class Alloc = alloc>
class set
{
public:typedef Key key_type;typedef Key value_type;typedef Compare key_compare;
private:typedef rb_tree<key_type, value_type, identity<value_type>, key_compare, Alloc> rep_type;rep_type t;
}
map中:
template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
class map
{
public:typedef Key key_type;typedef pair<const Key, T> value_type;typedef Compare key_compare;
private:typedef rb_tree<key_type, value_type, select1st<value_type>, key_compare, Alloc> rep_type;rep_type t;
}
观察可以发现,在定义成员变量的时候我们只用了一个t,它是rb_tree类型的,并且对于set来说,我们相当于传了两个相同的key到rb_tree的模板参数列表中
由此可以推断出,实际上的操作大都在类rb_tree中实现,而set与map中很可能只套上了一层外壳
1.2为什么要传入key_type与value_type两个呢?
观察rb_tree的源码来寻找答案
template <class Key, class Value, class KeyOfValue, class Compare,class Alloc = alloc>
class rb_tree {typedef __rb_tree_node_base* base_ptr;
typedef __rb_tree_node<Value> rb_tree_node;typedef __rb_tree_color_type color_type;
}
根据重定义,追溯到结点的定义
template <class Value>
struct __rb_tree_node : public __rb_tree_node_base
{typedef __rb_tree_node<Value>* link_type;Value value_field;
};
根据继承的基类,在此处定义三叉链表和颜色
struct __rb_tree_node_base
{typedef __rb_tree_color_type color_type;typedef __rb_tree_node_base* base_ptr;color_type color; base_ptr parent;base_ptr left;base_ptr right;
};
综合以上观察情况,我们可以得出:
map和set底层都是红黑树rb_tree,
此时他们会传入两个模板key_type与value_type,
对于set来说,传入的是<key,key>
而对于map来说,传入的是<key,pair<const Key, T>>
传入看似冗余的参数原因是:
①在map和set的实现过程中,rb_tree中节点进行typedef需要用到
value_type这一传过来对应Value的模板参数来申请节点,
如 rb_tree 中的
typedef __rb_tree_node<Value> rb_tree_node;
②除此之外,因为我们在find和erase的时候传入的是Key的类型,尤其是对于map来说,很明显不能够传入一个pair<K,V>来进行查找或者删除,所以只有Value很明显是不够的,为此我们要额外传入一个参数key_type对应传过来的参数Key。
1.3参数KeyOfValue的作用
在插入的过程当中,我们的一些操作需要直接对Value进行,但是比较的逻辑应该按照Key的来进行:
这一问题对于set来说还好,但是对于map来说我们却不能直接利用库函数重载的对于pair的比较
(库中pair的对比方式:例如对于<的重载,先看first的大小关系,first小就返回true,first大或者相等会再去比较second的大小关系)因为我们并不希望比较大小的过程涉及到second
为了解决这一问题,我们需要利用仿函数,具体的做法就是:
在rb_tree的模板类型中添加一个特殊的仿函数“KeyOfValue”,同时在map与set中分别实现不同逻辑的“MapKeyOfValue”和“SetKeyOfValue”在其中分别对operator()重载比较逻辑,返回pair中Key的值即可
之后在rb_tree的比较之前声明一个KeyOfValue类型的kot,实现比较逻辑的时候就可以
if(kot(cur->_data) < kot(data))
当然,如果对比较的方式还有要求,还可以再利用正常情况下的仿函数Compare
if(com(kot(cur->_data) , kot(data)))
1.3补:类模板中写本类的类型名,可以直接省略模板参数
如:
template<class K,class T>
class _ma
{//原写法:_ma(const _ma<K,T>& t){}//省略写法_ma(const _ma& t){}
}
这种设置在我们模板参数类型很多的时候可以起到很好的简化代码的作用
二、map与set的迭代器
2.1观察库中代码,理顺迭代器的实现逻辑
set中:
typedef typename rep_type::const_iterator iterator;
typedef typename rep_type::const_iterator const_iterator;
rep_type这一类型是之前对rb_tree类型的重定义,
typedef rb_tree<key_type, value_type, select1st<value_type>, key_compare, Alloc> rep_type;
同时我们发现map中也有完全相同的一句
typedef typename rep_type::iterator iterator;
typedef typename rep_type::const_iterator const_iterator;
由此可以推断map和set的迭代器都使用了rb_tree中的迭代器。
此时我们可以去rb_tree中寻找相应的迭代器来进行观察
在rb_tree中:
public:typedef __rb_tree_iterator<value_type, reference, pointer> iterator;
继续寻找__rb_tree_iterator的定义
template <class Value, class Ref, class Ptr>
struct __rb_tree_iterator : public __rb_tree_base_iterator
{typedef Value value_type;typedef Ref reference;typedef Ptr pointer;typedef __rb_tree_iterator<Value, Value&, Value*> iterator;typedef __rb_tree_iterator<Value, const Value&, const Value*> const_iterator;
}
从中可以发现Ref与Ptr这两个模板参数,与vector当中一样,他们也是为了const迭代器服务的;而除此之外,迭代器所需要的各种重载和接口也是在这一层实现的
再看基类:
struct __rb_tree_base_iterator
{typedef __rb_tree_node_base::base_ptr base_ptr;base_ptr node;
};
综合来看,迭代器中真正存的还是一个的__rb_tree_node_base*类型的节点指针
2.2根据库中逻辑进行总结
按照这一逻辑,我么可以选择在自行实现的RBTree中实现一个
template<class T,class Ref ,class Ptr>
struct RBTree_Iterator
其中存一个节点的指针Node* _node;
完成对它的构造,并在map和set中进行对应的typedef,迭代器的框架就搭好了
2.3迭代器类中的运算符重载与接口
2.3.1遍历需要的重载
要实现遍历,我们需要对三个运算符进行重载,它们分别是operator* ,operator++ ,operator!= ,operator->
其中*,->和!=逻辑与之前vector实现的过程类似,此处不再赘述
唯独++在重载过程中有这样一个问题:
红黑树的++需要我们走中序遍历,而不是简单的如链表一般的移动,该怎么做呢?
①首先明确中序遍历是: 左子树 根 右子树
②既然是++,那么其针对的并不一定会是整棵树,也有可能是树中的节点,
因此要实现的话,我们需要以局部的视角来看这个问题
假设:
1>情况一:当传入节点为it(例子中为11)时,传入节点的右子树不为空,++对应的节点就应该是右子树的最左节点(例子中为12),让_node对应的节点移到新对应节点上
2>情况二:当传入节点为it(例子中为7)时,右子树为空,代表当前子树走完了,根据中序遍历顺序,我们应该沿着到根节点的路径进行查找,直到找到“孩子是父亲的左孩子”此时对应的那一个祖先节点(例子中是8)就是下一个要访问的节点,此时为左子树走完
如果走到了根节点,那么就把_node置为nullptr,因为此时为右子树走完
2.3.2begin和end接口的实现
map和set中的begin和end可以直接调用rb_tree中的Begin和End来完成功能
①Begin
对应返回整颗子树的最左节点,只要循环查找即可找到对应位置的迭代器进行返回
②End
End的实现可以直接iterator(nullptr),这样的实现虽然不同于常规,但也可以保证这两点
1>树为空时,Begin和End返回值相等
2>树不为空时,指向有效节点的下一个(本来就是空)
2.3.2补:实现思路与源码的区别
其实在源码中是实现了一个哨兵位的头节点作为End的载体
哨兵位也是一个节点,节点的三叉链指向:
_parent:指向根节点,且根节点的_parent也指向哨兵位
_left:直接指向整颗子树的最左节点
_right:直接指向整颗子树的最右节点
这种实现的好处:
若是遇到这段代码
it=end();
--it;
可以让it对应的迭代器位置直接指向最后一个元素,也就是树的最右节点,符合了它双向迭代器的要求,
只是这一部分还算不得优点,毕竟在重载--也是要进行特殊情况特殊处理,
我们使用nullptr直接构造End也可以在重载--时处理一下
最重要的是有了哨兵位就可以更容易地拿到_root根节点地迭代器了,这一点是直接nullptr构造比不上的
2.3.3--运算符的重载与特殊
参考++时候地逻辑,--正好反向:右子树 根 左子树
实现看左子树是否为空:①为空,则为左子树地最右节点
②不为空,则说明右子树走完了,想上找cur是parent右孩子这种情况对应的parent,就是要的祖先节点
特殊处理:
在--对应的节点为nullptr的时候,我们直接查找整颗子树地最右节点,只是此时要拿到树的根节点,最直接地办法就是让迭代器类中多存一个结点指针的成员变量,这种情况下把_root传过来就是最好的解决办法了
用库中对应地结构可以避开这一额外传参的问题,但本质上各有利弊,在其他地方会有麻烦出现
2.4const迭代器
一如之前vector中控制const迭代器的方式,利用两个新的模板参数Ref与Ptr来做*与->的返回值,
之后在map和set以及RBTree中补充对应模板参数的const_iterator的重定义
特殊:
通常意义上const迭代器与普通迭代器的区别就是例如遍历过程中
*it之后不可以进行值的修改
但是,对于map和set以及RBTree而言不止const迭代器,普通迭代器也不能随意修改,否则会造成树结构的直接混乱,因此我们进行了如下措施:
set中定义成员变量
RBTree<K, const K, SetKeyOfT> _t;
map中定义成员变量
RBTree<K, pair<const K,V>, MapKeyOfT> _t;
都是通过const直接修饰来阻止对值进行修改
(在源码中,直接把set与map中的普通迭代器利用rb_tree中的const迭代器进行了typedef)
2.4补:如何保证const迭代器对应接口与原接口构成重载
如果直接
iterator begin()
{return _t.Begin();
}const_iterator begin()
{return _t.Begin();
}
只有返回值类型不同是无法构成函数重载的,因此我们需要利用const修饰成员函数来让重载顺利构成,即
const_iterator begin() const
{return _t.Begin();
}
2.补:迭代器的加深理解
迭代器可以说是一种实用性很高的封装的体现,
他把各种各样的容器如数组,链表,树,哈希,双端队列等等不同的容器统一typedef
使得使用者只需要 容器::iterator即可轻松进行遍历
迭代器屏蔽了底层的细节,提供了统一的访问方式
三、map和set需要的其余接口
3.1查找
find接口返回的是迭代器类型,实现思路可以是rb_tree中走搜索二叉树的查找,map和set中套壳
3.2插入
insert接口返回的是pair<iterator,bool>,实现思路可以是rb_tree中走红黑树的插入,成功/失败插入返回一个make_pair(),map和set中套壳
3.3map中对于[]的重载
依托于insert进行,传入key的值,直接用一个pair<iterator,bool>类型的值接收insert(key)的返回值,再return一下iterator->second即可
相关文章:
C++中map和set的封装
一、关于封装过程中传入的模板参数的问题 通过源码中的封装方式进行理解: 1.1map和set中成员变量 set中: template <class Key, class Compare less<Key>, class Alloc alloc> class set { public:typedef Key key_type;typedef Key v…...
dsa introduction 3
空间复杂度一般不会超过时间复杂度。空间复杂度就是申请的空间的数量级别。 减治和分治都是算法策略。都可以用递归和迭代的手段去实现。递归就是函数自己调用自己。一直到递归基之后再返回。递归算法的空间复杂度是递归深度。分治是分别求解子问题,然后由子问题的…...
C++ 日志库 spdlog 使用教程
Spdlog是一个快速、异步、线程安全的C日志库,他可以方便地记录应用程序的运行状态,并提供多种输出格式。官网:https://github.com/gabime/spdlog 安装教程可以参考:https://blog.csdn.net/Harrytsz/article/details/144887297 S…...
Pytorch机器学习——1 深度学习介绍
outline 人工智能、机器学习与深度学习深度学习工具介绍 1. 人工智能、机器学习与深度学习 AI:研究如何能让计算机模拟人类的智能,来实现特定的依赖人类智能才能实现的任务(例如学习、语言、识别) AI历史: 1818&#x…...
软件工程期末大复习(六)面向对象分析
6.1 软件分析概述 软件分析是软件开发生命周期中的一个关键阶段,它紧随需求收集之后。在这个阶段,分析者的目标是理解用户的需求,并确定系统应该做什么。 需求分析:分析用户的需求,确定系统必须实现的功能。概念性设计…...
科研绘图系列:R语言科研绘图之标记热图(heatmap)
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理画图系统信息参考介绍 科研绘图系列:R语言科研绘图之标记热图(heatmap) 加载R包 library(tidyverse) library(ggplot2) library(reshape)…...
数据挖掘——朴素贝叶斯分类
数据挖掘——朴素贝叶斯分类 朴素贝叶斯分类极大后验假设独立性假设贝叶斯分类器总结 朴素贝叶斯分类 什么是分类? 找出描述和区分数据类或概念的模型,以便能够使用模型预测未知的对象的类标号 概念区分 分类与回归 分类是预测分类(离散、…...
Redis数据库笔记—— Hash(哈希)的扩容机制(rehash)
大家好,这里是Good Note,关注 公主号:Goodnote,专栏文章私信限时Free。详细介绍Hash(哈希)的扩容机制(rehash)、源码、以及扩容和缩容过程。 文章目录 Redis 字典(dict)结构源码哈希…...
【Web】软件系统安全赛CachedVisitor——记一次二开工具的经历
明天开始考试周,百无聊赖开了一把CTF,还顺带体验了下二开工具,让无聊的Z3很开心🙂 CachedVisitor这题 大概描述一下:从main.lua加载一段visit.script中被##LUA_START##(.-)##LUA_END##包裹的lua代码 main.lua loca…...
面向对象分析与设计Python版 建模工具UML
文章目录 一、建模与模型二、统一建模语言 一、建模与模型 建模与模型 建模 modeling: 把不太理解的东西和一些已经较为理解、且十分类似的东西做比较,可以对这些不太理解的东西产生更深刻的理解,叫做建模重要的研发成果常常产自类比 模型 …...
Flink系列知识讲解之:深入了解 Flink 的网络协议栈
Flink系列知识之:深入了解 Flink 的网络协议栈 Flink 的网络协议栈是组成 flink-runtime 模块的核心组件之一,也是每个 Flink 任务的核心。它连接着来自所有任务管理器的各个工作单元(子任务)。这是流数据流过的地方,…...
动态库dll与静态库lib编程4:MFC规则DLL讲解
文章目录 前言一、说明二、具体实现2.1新建项目2.2 模块切换的演示 总结 前言 动态库dll与静态库lib编程4:MFC规则DLL讲解。 一、说明 1.前面介绍的均为Win32DLL,即不使用MFC的DLL。 2.MFC规则DLL的特点:DLL内部可以使用MFC类库、可以被其他…...
TypeScript 后端开发中的热重载编译处理
在一些除了nest框架外的一些其他nodejs框架中没有提供对ts编译和热重载,如果使用typescript我们需要自己进行配置。 方法一(推荐) 使用bun运行环境(快)。注:一些不是使用js,ts代码编写的第三方…...
ORB-SLAM3源码学习:LoopClosing.cc:LoopClosing::NewDetectCommonRegions检测共同区域
前言 在ORB-SLAM2中校验闭环候选关键帧时,需要满足时序上连续3次成功校验才能通过。这就需要检测至少3个新进来的关键帧,这种方法牺牲了召回率来提升精度。由于必须严格的满足至少连续的三个条件这使得闭环的条件更加严格,即使存在真实的闭环…...
前端React Router从入门到进阶实战
React Router 是 React 应用中的一个重要库,它用于实现客户端的路由管理,能够将 URL 路径与 React 组件关联起来,从而实现页面之间的导航。React Router 不会像传统的多页面应用那样重新加载页面,而是通过组件切换来呈现不同的视图…...
关于华硕Armoury Crate(奥创中心)安装程序失败、卡进度条问题解决方案
关于华硕Armoury Crate(奥创中心)安装失败解决方案 清理旧版本文件 如果之前安装过Armoury Crate,可能有残留文件导致冲突: 利用官方的卸载工具,卸载旧版本: https://www.asus.com.cn/supportonly/armoury%20crate/…...
【WPF】 数据绑定机制之INotifyPropertyChanged
INotifyPropertyChanged 是 WPF 中的一个接口,用于实现 数据绑定 中的 属性更改通知。它的主要作用是,当对象的某个属性值发生更改时,通知绑定到该属性的 UI 控件更新其显示内容。 以下是有关 INotifyPropertyChanged 的详细信息和实现方法&…...
QPushButton的基础用法
概述 本文将详细介绍 QPushButton 的概念、常规用法、样式表以及一些特殊用法,帮助您深入理解和高效应用 QPushButton。当前Qt版本为6.8。 1. QPushButton 的基本概念 1.1 概述 QPushButton 是 Qt 中最常用的按钮控件之一,它表示一个可以被点击的按钮…...
股指期货有哪些优势?
股指期货,作为一种重要的金融衍生品,以其独特的交易方式和多样的优势,吸引了众多投资者的关注。本文将详细解析股指期货的定义、优势以及特点,帮助投资者更好地理解和把握这一市场。 一、股指期货的定义 股指期货,顾…...
STM32完全学习——FATFS0.15移植SD卡
一、下载FATFS源码 大家都知道使用CubMAX可以很快的将,FATFS文件管理系统移植到单片机上,但是别的芯片没有这么好用的工具,就需要自己从官网下载源码进行移植。我们首先解决SD卡的驱动问题,然后再移植FATFS文件管理系统。 二、SD…...
使用 Spring 状态机构建灵活的状态管理系统
引言 在软件开发中,状态机是一种非常重要的工具,尤其适用于需要处理复杂状态转换的场景。无论是订单管理系统中的订单状态、工作流引擎中的任务流转,还是审批流程的管理,状态机都能有效地帮助我们组织和管理不同的状态及其之间的…...
[SMARTFORMS] 添加设置图标
本地图片存放位置 使用事务码SE78进入表格图形管理页面,将导入图标到SAP系统 选择需要上传的图片地址,输入名称,描述和图片类型,点击导入按钮 完成上述操作以后,图标已导入到SAP系统中 提示Tips:如何将图标…...
网络世界的“交通规则”——TCP/IP(一)
一、非可靠传输的协议——UDP 1.1 UDP的报文格式 (1)UDP长度:表示整个UDP数据包的长度(报头载荷); (2)校验和:用于验证UDP数据包在传输过程中有没发生比特翻转ÿ…...
Excel中公式和函数的区别
Excel中公式和函数的区别 概念讲解例子公式函数 详细介绍函数面板最后再次进行演示操作文档 概念讲解 公式是用户自己编写的表达式,而函数是由Excel预定义的操作。公式可以包含各种数学运算符和逻辑表达式,函数则是执行特定任务的工具。公式可以引用其他…...
Node.js应用程序遇到了内存溢出的问题
vue 项目 跑起来,一直报错,内存溢出 在 文件node_modules 里 .bin > vue-cli-service.cmd 在依赖包这个文件第一行加上这个 node --max-old-space-size102400 "%~dp0\..\vue\cli-service\bin\vue-cli-service.js" %* node --max-old-s…...
MySQL关联关系理论与实践
MySQL 是一种关系型数据库管理系统,以其高性能、灵活性和易用性在开发者中广受欢迎。在 MySQL 中,数据存储以表格形式存在,表与表之间的关联关系构成了关系型数据库的核心。本篇文章将介绍 MySQL 关联关系的理论基础和常见实践,包…...
w138基于Spring Boot的宠物领养系统的设计与实现
🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...
AMBA-CHI协议详解(十三)
AMBA-CHI协议详解(一)- Introduction AMBA-CHI协议详解(二)- Channel fields / Read transactions AMBA-CHI协议详解(三)- Write transactions AMBA-CHI协议详解(四)- Other transac…...
组合的能力
在《德鲁克最后的忠告》一书中,有这样一段话: 企业将由各种积木组建而成:人员、产品、理念和建筑。积木的设计组合至少和其供给一样重要。……对于一切程序、应用软件以及附件来说,重要的是掌握将已有的软件模块组合的能力&…...
若依使用 Undertow 替代 Tomcat 容器
文章目录 需求提出应用场景解决思路注意事项完整代码第一步:在 ruoyi-framework/pom.xml 文件中进行依赖配置第二步:修改 application.yml 配置文件第三步:修改文件上传工具类 FileUploadUtils.java 运行结果 需求提出 在开发若依框架的前后…...
STC单片机 IAP在线升级功能的使用介绍
STC单片机 IAP在线升级功能的使用介绍 从官方给出的IAP在线升级的demo示例来看,目前支持的型号有STC8、STC12、STC15、STC32,前提是需要使用64K/128K容量的型号。只支持用户程序容量小于60K 的项目。 🌿IAP在线升级方式支持:CAN、…...
visio 0xC004F017
1.好久没用的电脑突然显示Office tool plus 的软件(visio)失效了 显示错误代码: 0xC004F017 2.在软件中重新配置 关键:KMS用了 kms.03k.org 3.在软件中重新配置 许可选择 4.一些额外的检查方法 打开控制台输入 slmgr /dlv 中间过程 还遇到过【错误…...
IoC设计模式详解:控制反转的核心思想
前言:在软件开发中,设计模式是一种经过验证的、在特定场景下能有效解决问题的解决方案。控制反转(Inversion of Control,IoC) 作为一种设计模式,通过让程序的控制流和对象管理反转,从而使得代码…...
C语言延时实现
C语言延时实现 在C语言中,delay 函数通过空循环实现延时,而不是像其他高级语言(如Python)直接使用 sleep 函数。这种实现方式是基于单片机的特性和C语言的底层操作。下面详细解释为什么这种空循环可以实现延时,以及它…...
CDP集群安全指南-静态数据加密
[一]静态数据加密的架构 CDP 支持两种加密组件,这些组件可以组合成独特的解决方案。在选择密钥管理系统(KMS)时,您需要决定哪些组件能够满足企业的密钥管理和加密需求。 CDP 加密组件 以下是 Cloudera 用于静态数据加密的组件描…...
# LeetCode Problem 2038: 如果相邻两个颜色均相同则删除当前颜色 (Winner of the Game)
LeetCode Problem 2038: 如果相邻两个颜色均相同则删除当前颜色 (Winner of the Game) 在本篇博客中,我们将深入探讨 LeetCode 第2038题——如果相邻两个颜色均相同则删除当前颜色。该问题涉及字符串处理与游戏策略,旨在考察如何在给定规则下判断游戏的…...
极限学习机 (Extreme Learning Machine, ELM) 算法详解与PyTorch实现
极限学习机 (Extreme Learning Machine, ELM) 算法详解与PyTorch实现 目录 极限学习机 (Extreme Learning Machine, ELM) 算法详解与PyTorch实现1. 极限学习机 (ELM) 算法概述1.1 单隐层前馈神经网络1.2 ELM的优势2. ELM的核心技术2.1 模型定义2.2 随机初始化2.3 最小二乘法2.4…...
【insert 插入数据语法合集】.NET开源ORM框架 SqlSugar 系列
系列文章目录 🎀🎀🎀 .NET开源 ORM 框架 SqlSugar 系列 🎀🎀🎀 文章目录 系列文章目录一、前言 🍃二、插入方式 💯2.1 单条插入实体2.2 批量 插入实体2.3 根据字典插入2.4 根据 Dat…...
什么是.net framework,什么是.net core,什么是.net5~8,版本对应关系
我不知道有多少人和我一样,没学习过.netCore,想要学习,但是版本号太多就蒙了,不知道学什么了,这里解释下各个版本的关系 我们一般开始学习微软的时候,都是开始学习的.netframework,常用的就是4…...
【数据库系统概论】数据库安全性和存取控制和视图机制以及审计、数据加密--复习极简总结版
1. 数据库安全性概述 1.1 数据库安全性的重要性 数据库安全性是保护数据库防止非法访问、数据泄露、篡改或破坏的能力。它随着数据共享和网络化应用的普及而变得至关重要。现实案例: 2016年,某国医院遭受黑客攻击,黑客加密数据库并勒索赎金…...
深入理解计算机系统—虚拟内存(3)
9.9 动态内存分配 虽然可以使用低级的 mmap 和 munmap 函数来创建和删除虚拟内存的区域,但是 C程序员还是会觉得当运行时需要额外虚拟内存时,用 动态内存分配器 更方便,也有更好的可移植性。 动态内存分配器维护着一个进程的虚拟内存区域&…...
Vue项目整合与优化
前几篇文章,我们讲述了 Vue 项目构建的整体流程,从无到有的实现了单页和多页应用的功能配置,但在实现的过程中不乏一些可以整合的功能点及可行性的优化方案,就像大楼造完需要进行最后的项目验收改进一样,有待我们进一步…...
MyBatis 与 MyBatis-Plus 的区别
MyBatis 和 MyBatis-Plus 都是用于简化 Java 应用程序与数据库交互的持久层框架,但它们在功能、易用性和性能优化方面存在显著差异。下面将详细介绍两者之间的区别,并通过具体的代码示例进行对比。 概述 MyBatis:作为一款经典的持久层框架&a…...
如何让大模型不再“已读乱回”——RAG技术助力生成更精确的答案
随着大语言模型(LLM) 的迅猛发展,越来越多的领域开始受益于其强大的自然语言处理能力。从写作到编程,LLM已成为我们日常生活和工作的得力助手。然而,这些看似无所不能的大模型,却有一个致命的弱点ÿ…...
Anaconda环境配置(Windows11+python3.9)
文章目录 一、 下载ANACONDA(1)点击**Free Download**。(2)点击“skip registration”,跳过登录。(3)下载对应操作系统的ANACONDA版本。 二、 安装ANACONDA(1)双击运行安…...
Spring Boot 中的虚拟线程
什么是虚拟线程? 虚拟线程(Virtual Threads)是 Java 19 引入的一项新特性,它属于 Project Loom 项目的一部分。与传统的线程(平台线程)不同,虚拟线程并不是由操作系统直接管理,而是…...
el-table 实现纵向多级表头
为了实现上图效果,最开始打算用el-row、el-col去实现,但发现把表头和数据分成两大列时,数据太多时会导致所在格高度变高。但由于每一格数据肯定不一样,为保持高度样式一致,就需要我们手动去获取最高格的高度之后再设置…...
探秘Kafka源码:关键内容解析
文章目录 一、以kafka-3.0.0为例1.1安装 gradle 二、生产者源码2.1源码主流程图2.2 初始化2.3生产者sender线程初始化2.4 程序入口2.5生产者 main 线程初始化2.6 跳转到 KafkaProducer构造方法 一、以kafka-3.0.0为例 打开 IDEA,点击 File->Open…->源码包解…...
Promise编码小挑战
题目 我们将实现一个 createImage 函数,该函数返回一个 Promise,用于处理图片加载的异步操作。此外,还会实现暂停执行的 wait 函数。 Part 1: createImage 函数 该函数会: 创建一个新的图片元素。将图片的 src 设置为提供的路径…...
PyQt实战——将pcm文本数据转换成.pcm的二进制文件
系类往期文章: PyQt5实战——多脚本集合包,前言与环境配置(一) PyQt5实战——多脚本集合包,UI以及工程布局(二) PyQt5实战——多脚本集合包,程序入口QMainWindow(三&…...