【C++进阶】四、STL---set和map的介绍和使用
目录
一、关联式容器
二、键值对
三、树形结构的关联式容器
四、set的介绍及使用
4.1 set的介绍
4.2 set的使用
五、multiset的介绍及使用
六、map的介绍和使用
6.1 map的介绍
6.2 map的使用
七、multimap的介绍和使用
一、关联式容器
前面已经接触过 STL 中的部分容器,比如:vector、list、deque等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身
什么是关联式容器?
关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是 <key, value> 结构的键值对,在数据检索时比序列式容器效率更高
set 和 map 便是关联式容器
二、键值对
什么是键值对?
键值对是用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息
比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义
在 set 和 map 就使用了键值对,这个键值对名为 pair,他是一个 struct 定义的类模板,即可以在外部访问 pair 里面的成员变量
SGI-STL中关于键值对的定义如下:
template <class T1, class T2>
struct pair
{typedef T1 first_type;typedef T2 second_type;T1 first;T2 second;pair() : first(T1()), second(T2()){}pair(const T1& a, const T2& b) : first(a), second(b){}
};
pair文档介绍:pair - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/utility/pair/?kw=pair
成员类型介绍如下:
如何使用 pair ,下面介绍 set 和 map 再解释
三、树形结构的关联式容器
根据应用场景的不同,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构
树型结构的关联式容器主要有四种:map、set、multimap、multiset,这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列
四、set的介绍及使用
4.1 set的介绍
set文档介绍:set - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/set/set/?kw=set
翻译如下:
- set是按照一定次序存储元素的容器
- 在set中,元素的 value 也标识它(value就是key,类型为T),并且每个value 必须是唯一的。set 中的元素不能在容器中修改(元素总是 const),但是可以从容器中插入或删除它们
- 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序
- set 容器通过 key 访问单个元素的速度通常比 unordered_set 容器慢,但它们允许根据顺序对子集进行直接迭代
- set 在底层是用二叉搜索树(红黑树)实现的
set 的模板参数有三个:
- 第三个模板参数 class Alloc = allocator<T> 是空间配置器,不用理会
- 第二个模板参数 class Compare = less<T> 是仿函数,平时不用理会,使用缺省值即可,前面也介绍过了,有需要再传参,set 中元素默认按照小于来比较
- 第一个模板参数 class T 是 set 中存放元素的类型,实际在底层存储 <value, value> 的键值对
注意:
- 与 map/multimap 不同,map/multimap 中存储的是真正的键值对 <key, value>,set/multiset 中只放 value,但在底层实际存放的是由<value, value>构成的键值对
- set 中插入元素时,只需要插入value 即可,不需要构造键值对
- 即 set/multiset 为 K模型,map/multimap 为 KV模型
使用set要包含头文件:
#include <set>
注意:set中的元素不可以重复(因此可以使用set进行去重)
4.2 set的使用
先介绍一下set的前四个成员类型
- key_type 是第一个模板参数,即(T),value_type 也是第一个模板参数(T)
- value_type 对应键值对 pair 的第一个模板参数(T1),value_type 对应键值对 pair 的第一个模板参数(T2),即 <key_type,value_type>
- key_compare 是第二个模板参数(Compare),key_compare 也是第二个模板参数(Compare)
- key_compare 和 value_compare 也是键值对,与上面类似
(1)set 的构造函数
set 提供的构造函数有:第一个空构造和 第二个迭代器区间构造,一般都使用空构造,第三个是拷贝构造函数
测试代码
void Test_Set()
{set<int> s1;//空构造set<int> s2(s1.begin(), s1.end());//区间构造set<int> s3(s1);//拷贝构造
}
(2)赋值重载
测试代码
void Test_Set()
{set<int> s1;//空构造set<int> s2(s1);//拷贝构造set<int> s3;s3 = s1;//赋值重载
}
析构函数,这个就不介绍了,程序结束自动调用
(4)Iterators
使用 set 的迭代器遍历set中的元素,可以得到有序序列
(5) Capacity
(6)Modifiers
set中的元素不允许修改
(7)find
set 中查找某个元素,时间复杂度为:logN
以上接口都与之前学的容器接口用法大致相同,就不再演示了
五、multiset的介绍及使用
multiset的文档介绍:multiset - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/set/multiset/
翻译:
- multiset是按照特定顺序存储元素的容器,其中元素是可以重复的
- 在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成的键值对,因此value本身就是key,key就是value,类型为T). multiset元素的值不能在容器中进行修改(因为元素总是const的),但可以从容器中插入或删除
- 在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序
- multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时会得到一个有序序列
- multiset底层结构为二叉搜索树(红黑树)
模板参数和成员类型与set一致,不解释了
注意:
- multiset中再底层中存储的是<value, value>的键值对
- mtltiset的插入接口中只需要插入即可
- 与set的区别是,multiset中的元素可以重复,set 是中value是唯一的
- 使用迭代器对multiset中的元素进行遍历,可以得到有序的序列
- multiset中的元素不能修改
- 在multiset中找某个元素,时间复杂度为O(logN)
- multiset的作用:可以对元素进行排序
multiset 的使用与 set一致,最大区别就是:set去重+排序,multiset元素可重复+排序
注意:查找的元素是相同元素的时候,返回的是中序遇到相同的第一个元素的迭代器
使用 multiset 要包含头文件:
#include <set>
六、map的介绍和使用
6.1 map的介绍
map的文档介绍:map - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/map/map/?kw=map
翻译:
- map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素
- 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与 value通过成员类型 value_type 绑定在一起,为其取别名称为 pair
- typedef pair<const Key, T> value_type
- 在内部,map中的元素总是按照键值key进行比较排序的
- map中通过键值访问单个元素的速度通常比 unordered_map 容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)
- map支持下标访问符,即在[]中放入key,就可以找到与key对应的 value
- map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))
map 的模板参数有4个
- 第四个模板参数 class Alloc = allocator<pair<const Key, T> > 是空间配置器,现在不用理会
- 第三个模板参数 class Compare = less<Key> 是仿函数,平时不用理会,使用缺省值即可,前面也介绍过了,有需要再传参,默认按照小于来比较
- 第二个模板参数 class T 是键值对中 value 的类型
- 第二个模板参数 class Key 是键值对中 key 的类型
注意:Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
使用 map 需要包含头文件:
#include <map>
注意:map 也是去重+排序
6.2 map的使用
先介绍 map成员类型:
- key_type 是第一个模板参数(Key)
- mapped_type 是第二个模板参数(T)
- value_type 是 pair<const key_type, mapped_type> 进行 typedef 得到的
- key_compare 是第三个模板参数(Compare),比较的是 key_type(Key),缺省值为 less
- value_compare 是用于比较元素的嵌套函数类
map接口跟 set差不多,但是 map多了随机访问的接口,对 map很重要,下面介绍
(1)构造函数
测试代码
void Test_Map()
{//KV模型,通过 Key查找Value//map<Key, Value>map<int, char> m1;//空构造map<int, string> m2;//空构造map<int, char> m3(m1.begin(), m1.end());//区间构造map<int, char> m4(m1);//拷贝构造
}
(2)赋值重载
void Test_Map()
{map<int, char> m1;//空构造map<int, char> m2(m1);//拷贝构造//赋值重载map<int, char> m3;m3 = m1;
}
析构函数自动调用,不解释
(3)Iterators
支持迭代器则支持范围 for
测试代码
void Test_Map()
{map<int, char> m1;//空构造//插入数据。后面解释m1.insert(make_pair(1, 'a'));m1.insert(make_pair(2, 'b'));m1.insert(make_pair(3, 'c'));m1.insert(make_pair(4, 'd'));m1.insert(make_pair(4, 'd'));//key已存在则不插入,map去重//遍历//map<int, char>::iterator it = m1.begin();auto it = m1.begin();while (it != m1.end()){//通过Key查找Value//first是Key,second是Value,(KV模型)//键值对 pair<T1, T2> ---> pair<first, second>cout << it->first << "-->" << it->second << endl;++it;}cout << endl;//范围forfor (auto& e : m1)//建议加上引用,否则数据大量的时候会带来拷贝大的代价{cout << e.first << "-->" << e.second << endl;}
}
运行结果
(4)Capacity
一个判空和一个返回数据的大小,就不演示了
(5)Modifiers
swap 和 clear 不演示了,下面介绍 insert 和 erase
erase接口如下
常用就是传 Key 删除节点,不多解释
insert 接口如下:
最常用就是第一个,问题来了,pair<iterator, bool> 是什么??
先看 insert 接口解释:
- 参数类型 value_type 是 pair<const key_type, mapped_type> 进行 typedef 得到的,也就是说参数是一个键值对,并使用引用传参
- insert 第一个(框起来的)的返回类型为 pair<iterator, bool>
- pair<iterator, bool> 第一个iteratior是迭代器,第二个是 bool,用于反映是否插入成功,成功返回true,否则返回false
- 如果插入成功(即元素不存在进行插入),返回为 pair<iterator, true>,迭代器返回的是新插入元素位置的迭代器(pair)
- 如果插入失败(即元素已经存在),返回为 pair<iterator, false>,迭代器返回的是已存在元素位置的迭代器(pair)
注:这个对下面理解 [] 很重要
测试代码
void Test_Map()
{map<int, char> m1;//空构造//插入也要指明键值对的类型 pair<T1, T2>m1.insert(pair<int, char>(1, 'a'));m1.insert(pair<int, char>(2, 'b'));// pair<T1, T2> 也可以写成 make_pairm1.insert(make_pair(3, 'c'));m1.insert(make_pair(4, 'd'));m1.insert(make_pair(4, 'd'));//key已存在则不插入,map去重for (auto& e : m1)//建议加上引用,否则数据大量的时候会带来拷贝大的代价{cout << e.first << "-->" << e.second << endl;}
}
运行结果
解释一下 make_pair
make_pair 是一个模板函数,在 pair 的文档有介绍
make_pair 定义如下:
简单来说,这个函数的功能就像是给 pair<T1, T2> 进行 typedef 为 make_pair,直接使用即可
注:pair<T1, T2>(x, y)是一个匿名对象
下面解释 map的随机访问
(6)Element access
接口如下:
operator[] 接口定义如下
operator[] 访问的条件是:只需传入第一个模板参数,即 Key 的值,也就是说 [] 访问是通过 Key 来进行访问的
operator[] 详情如下:
翻译:
- 如果k(Key)与容器中元素的键匹配(即Key存在),则函数返回对其映射值的引用,即返回 Key 值的引用
- 如果k(Key)与容器中任何元素的键不匹配(即Key不存在),函数将插入具有该键的新元素,并返回对其映射值的引用,即返回 新插入 Key 值的引用
- 注意,即使没有为元素分配映射值(即不给T传值,T为空),该元素使用其默认构造函数构造,插入新元素后,这会将容器大小增加1
- at 成员函数功能与 [] 类似,但是在具有键的元素存在时具有相同的行为(即查找的元素 Key 是存在的时候,at 和 [] 的功能是一样的),但在不存在时抛出异常(即查找的 Key 不存在,[] 的功能是把这个 Key 直接插入map中,但是 at 是抛异常,不会进行插入)
总结:
- [] 的功能是 查找+修改+插入 (修改的原因是 [] 返回 mapped_type(T)值的引用)
- at 的功能是 查找+修改(不支持插入)
[] 等价于:
(*((this->insert(make_pair(k, mapped_type()))).first)).second
- make_pair(k, mapped_type()) 第一个参数k(Key)为 pair 第一个模板参数T1
- 第二个参数 mapped_type() 是一个匿名对象,为 pair 第二个模板参数T2,mapped_type 是 map 第二个模板参数T,即T()
(*((this->insert( make_pair(k, mapped_type()) )).first)).secondmake_pair(k, mapped_type())
make_pair 返回的类型是 pair<T1, T2>,make_pair 返回 pair<T1, T2>,insert 进行接收, 把 pair<T1, T2> (x, y)作为insert 的参数,即参数 const value_type& val
也就是说
(*((this->insert( make_pair(k, mapped_type()) )).first)).second
可以转换为(方便理解):
mapped_type& operator[] (const key_type& k)
{return (*((this->insert( make_pair(k, mapped_type()) )).first)).second
}---
T& operator[](const Key& k)
{pair<iterator,bool> ret = insert( make_pair(k, T());//insert 返回 pair<iterator,bool>//迭代器在pair的first的位置(即用 . 可以访问pair的成员变量 first)//迭代器内容访问方式为 ->//-> 操作符的重载前面篇章有过解释return ret.first->second;
}
假设给你一个 string,要统计水果出现的次数
string arr[] = { "苹果", "西瓜", "香蕉", "草莓", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
可以使用map进行统计,代码如下:
void Test_Map()
{//统计水果出现的次数string arr[] = { "苹果", "西瓜", "香蕉", "草莓", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };map<string, int> countMap1;for (auto& e : arr){//map<string, int>::iterator it = countMapauto it = countMap1.find(e);if (it == countMap1.end())//没有就进行插入{countMap1.insert(make_pair(e, 1));}else{it->second++;}}for (const auto& kv : countMap1){cout << kv.first << ":" << kv.second << endl;}cout << endl;//使用 []map<string, int> countMap2;for (auto& e : arr){//不存在则插入//[] 的功能是 查找+修改+插入//operator[]的原理是:// 用<key, T()>构造一个键值对,然后调用insert()函数将该键值对插入到map中// 如果key已经存在,插入失败,insert函数返回该key所在位置的迭代器// 如果key不存在,插入成功,insert函数返回新插入元素所在位置的迭代器// operator[]函数最后将insert返回值键值对中的value返回countMap2[e]++;}for (const auto& kv : countMap2){cout << kv.first << ":" << kv.second << endl;}
}
运行结果
总结
- map中的的元素是键值对
- map中的key是唯一的,并且不能修改
- 默认按照小于的方式对key进行比较
- map中的元素如果用迭代器去遍历,可以得到一个有序的序列
- map的底层为平衡搜索树(红黑树),查找效率logN
- map支持[]操作符,operator[]中实际进行插入查找
(7) find
直接使用,就不解释了,不懂看文档
七、multimap的介绍和使用
multimap文档的介绍:multimap - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/map/multimap/
翻译:
- Multimaps是关联式容器,它按照特定的顺序,存储由key和value映射成的键值对<key,value>,其中多个键值对之间的key是可以重复的
- 在multimap中,通常按照key排序和惟一地标识元素,而映射的value存储与key关联的内容。key和value的类型可能不同,通过multimap内部的成员类型value_type组合在一起,value_type是组合key和value的键值对: typedef pair<const Key, T> value_type;
- 在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对key进行排序的
- multimap通过key访问单个元素的速度通常比unordered_multimap容器慢,但是使用迭代器直接遍历multimap中的元素可以得到关于key有序的序列
- multimap在底层用二叉搜索树(红黑树)来实现
注意:multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以重复的
multimap的使用和map一致,就不解释了
注意:
- multimap中没有重载 operator[] 操作,因为 multimap 的 Key 可能不唯一
- 使用时与map包含的头文件相同
----------------我是分割线---------------
文章到这里就结束了,下一篇即将更新
相关文章:

【C++进阶】四、STL---set和map的介绍和使用
目录 一、关联式容器 二、键值对 三、树形结构的关联式容器 四、set的介绍及使用 4.1 set的介绍 4.2 set的使用 五、multiset的介绍及使用 六、map的介绍和使用 6.1 map的介绍 6.2 map的使用 七、multimap的介绍和使用 一、关联式容器 前面已经接触过 STL 中的部分…...

JavaSE学习进阶 day1_01 static关键字和静态代码块的使用
好的现在我们进入进阶部分的学习,看一张版图: 前面我们已经学习完基础班的内容了,现在我们已经来到了第二板块——基础进阶,这部分内容就不是那么容易了。学完第二板块,慢慢就在向java程序员靠拢了。 面向对象进阶部分…...

苹果笔可以不买原装吗?开学必备性价比电容笔
在当今的时代,电容笔日益普及,而且相关的功能也逐渐完善。因此,在使用过程中,怎样挑选一款性价比比较高的电容笔成为大家关心的焦点。随着电容笔的普及,更好更便宜的电容笔成为了一种趋势。那么,哪个品牌的…...

数据库连接与properties文件
管理properties数据库: 现在pom文件中加入Druid的坐标: <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version></dependency>配置文件中添加相应的数据&…...

Linux上的校验和验证
校验和(checksum)程序用来从文件中生成相对较小的唯一密钥。我们可以重新计算该密钥,用以检查文件是否发生改变。修改文件可能是有意为之(添加新用户会改变密码文件),也可能是无意而为(从CD-ROM…...

杂记——14.git在idea上的使用及其实际开发介绍
这篇文章我们来讲一下git在idea上的使用,以及在实际开发过程中各个分支的使用及其具体的流程 目录 1.git在idea上的使用 1.1 idea上的git提交 1.2 idea上的分支切换 2.git在实际运用时的分支及其流程 2.1分支介绍 2.2具体流程 3.小结 1.git在idea上的使用 …...

记一次Nodejs减低npm版本的踩坑日记
使用了npm install -g npm6.4.1指令之后,把npm版本减低了,让后悲催的就来了。 由于npm 6.4.1 已经过时,导致运行npm时出现 npm does not support Node.js v18.14.2 版本不兼容问题 升级npm版本,npm install -g npmlatest 没用还是…...

【iOS】—— 初识RAC响应式编程
RAC(ReactiveCocoa) 文章目录RAC(ReactiveCocoa)响应式编程和函数式编程的区别函数式编程响应式编程响应式编程的优点RAC操作1.利用button点击实现点击事件和传值2.RACSignal用法RACSignal总结:3.对于label的TapGestur…...

Java——面向对象
目录 前言 一、什么是面向对象? 面向过程 & 面向对象 面向对象 二、回顾方法的定义和调用 方法的定义 方法的调用 三、类与对象的创建 类和对象的关系 创建与初始化对象 四、构造器详解 五、创建对象内存分析 六、封装详解 七、什么是继承&#x…...

电影《毒舌律师》观后感
上周看了《毒蛇律师》这部电影,讲述一位’大律师’在法庭为己方辩护,最终赢得辩护的故事。 (1)人之常情 说起法律相关,不禁会让人联想到讲法律相关知识的罗翔老师,平时也会看他相关视频,无论是亲…...

【活学活用掌握trap命令】
trap 命令用于指定在接收到信号后将要采取的动作,常见的用途是在脚本程序被中断时完成清理工作。当 shell 接收到 sigspec 指定的信号时, arg 参数(通常是执行命令)会被读取,并被执行。 1. 命令介绍 开始掌握基本的使用方式和方法 [1] 语法…...

计算机组成原理4小时速成6:输入输出系统,io设备与cpu的链接方式,控制方式,io设备,io接口,并行串行总线
计算机组成原理4小时速成6:输入输出系统,io设备与cpu的链接方式,控制方式,io设备,io接口,并行串行总线 2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,…...

MyBatis源码分析(三)SqlSession的执行主流程
文章目录一、熟悉主要接口二、SqlSession的获取1、通过数据源获取SqlSession三、Mapper的获取与代理1、从SqlSession获取Mapper2、执行Mapper方法前准备逻辑3、SqlCommand的创建4、构造MethodSignature四、执行Mapper的核心方法1、执行Mapper的方法逻辑五、简单SELECT处理过程1…...

环境搭建01-Ubuntu16.04如何查看显卡信息及安装NVDIA显卡驱动
1. 查看显卡型号、驱动 ubuntu-drivers devices2. 安装NVIDIA显卡驱动 (1)验证是否禁用nouveau lsmod | grep nouveau若有输出,没有禁用,进行以下操作禁用。 sudo gedit /etc/modprobe.d/blacklist.conf在文件末尾中添加两条&…...
内网渗透测试理论学习之第四篇内网渗透域的横向移动
文章目录一、IPC二、HashDump三、PTH四、PTT五、PsExec六、WMI七、DCOM八、SPN九、Exchange在内网中,从一台主机移动到另外一台主机,可以采取的方式通常有文件共享、计划任务、远程连接工具、客户端等。 一、IPC IPC(Internet Process Conn…...

20 | k8s v1.20集群搭建master和node
1 单节点master 1.1 服务器整体规划 1.2 单Master架构图 1.3 初始化配置 1.3.1 关闭防火墙 systemctl stop firewalld systemctl disable firewalld1.3.2 关闭selinux sed -i s/enforcing/disabled/ /etc/selinux/config # 永久 setenforce 0 # 临时 1.3.3 关闭swap …...

《商用密码应用与安全性评估》第一章密码基础知识1.1应用概念
密码的概念与作用 概念 密码:采用特定变换的方法对信息进行加密保护、安全认证的技术、产品和服务。 密码技术:密码编码、实现、协议、安全防护、分析破译、以及密钥产生、分发、传递、使 用、销毁等技术。 密码技术核心:密码算法…...

【博学谷学习记录】超强总结,用心分享丨人工智能 深度学习 神经网络基础知识点总结
目录神经网络激活函数引入激活函数原因:sigmoid激活函数tanh 激活函数ReLU 激活函数(最常用)SoftMax如何选择反向传播参数初始化方法优化方法正则化批量归一层网络模型调优的思路神经网络 简单的神经网络包括三层:输入层…...

Python+tkinter添加滚动条
大家好,我是IKUN的真爱粉,有时候我们需要在tkinter上加滚动条,那么怎么制作呢,我们先看下面的视频展示效果,是不是你想要的 展示 感觉制作的略微粗糙,各位可以后期自己慢慢调整 创建滚动条重要的步骤是&a…...

大V龚文祥造谣董明珠恋情被禁言
我是卢松松,点点上面的头像,欢迎关注我哦! 因造谣董明珠与王自如恋情,知名大V龚文祥老师被今日头条禁言。龚文祥说,69岁的董明珠,找了一个小自己34岁的男友,引的网友议论纷纷。 2月26日&#…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...