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

【C++】set、multiset与map、multimap的使用

目录

  • 一、关联式容器
  • 二、键值对
  • 三、树形结构的关联式容器
    • 3.1 set
      • 3.1.1 模板参数列表
      • 3.1.2 构造
      • 3.1.3 迭代器
      • 3.1.4 容量
      • 3.1.5 修改操作
    • 3.2 multiset
    • 3.3 map
      • 3.3.1 模板参数列表
      • 3.3.2 构造
      • 3.3.3 迭代器
      • 3.3.4 容量
      • 3.3.5 修改操作
      • 3.3.6 operator[]
    • 3.4 multimap

一、关联式容器

谈到关联式容器,先来说说序列式容器,以前学习的vector、list、deque等就是序列式容器,它们的特点是底层为线性序列的数据结构,存储的是元素本身。关联式容器也是存储数据的,不同的是,里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高。

二、键值对

键值对是用来表示一一对应关系的结构该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息,比如汉英互译字典,查中文就可以找到对应的英文,是有对应关系的。

键值对的定义:

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)
{}
};

三、树形结构的关联式容器

STL总共有两种结构的关联式容器,分别是哈希结构和树形结构。树形结构主要有4种:set、multiset、map、multimap,它们的共同点是底层是平衡搜索树即红黑树实现的,且容器中的元素是一个有序的序列。

3.1 set

特点:

  1. 遍历set中的元素,可以得到一个有序序列,因为它的底层实现是红黑树,再底层是二叉搜索树,遍历方式是中序遍历。
  2. set中的元素不可以重复,因此可以用set去重。
  3. 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。
  4. set中插入元素时,只需要插入value即可,不需要构造键值对。
  5. set中的元素默认按照小于来比较。
  6. set中查找某个元素,时间复杂度为:logN,即最多高度次。
  7. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。
  8. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。
  9. set中的元素不允许修改,因为修改了其中的一个元素会改变内部的结构,从而影响有序性。
  10. set在底层是用二叉搜索树(红黑树)实现的。

3.1.1 模板参数列表

在这里插入图片描述

  • T: set中存放元素的类型,实际在底层存储<value, value>的键值对。
  • Compare:set中元素默认按照小于来比较。
  • Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理。

3.1.2 构造

1️⃣构造空的set:

set<int> s;

2️⃣用迭代器区间构造:

set<int> s1(s.begin(), s.end());

3️⃣拷贝构造:

set<int> s2(s);

3.1.3 迭代器

1️⃣begin+end
正向遍历

	set<int> s;s.insert(1);s.insert(3);s.insert(3);s.insert(3);s.insert(5);s.insert(2);set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;

这里顺便检验下是否去重且有序:
在这里插入图片描述

2️⃣rbegin+rend
与上面类似,只不过是反向遍历

	set<int>::reverse_iterator rit = s.rbegin();while (rit != s.rend()){cout << *rit << " ";++rit;}cout << endl;

在这里插入图片描述

3.1.4 容量

1️⃣empty
判断set是否为空,空返回true,否则返回true

	set<int> s;cout << s.empty() << endl;//1

2️⃣size
返回set中有效元素的个数

set<int> s;
s.insert(1);
s.insert(3);
s.insert(3);
s.insert(3);
s.insert(5);
s.insert(2);
cout << s.size() << endl;//4

3.1.5 修改操作

1️⃣insert

pair<iterator,bool> insert ( const value_type& x )

在set中插入元素x,实际插入的是<x, x>构成的键值对,如果插入成功,返回<该元素在set中的位置,true>,如果插入失败,说明x在set中已经存在,返回<x在set中的位置,false>。

set<int> s;
s.insert(1);
s.insert(3);
s.insert(3);
s.insert(3);
s.insert(5);
s.insert(2);
for (auto& e : s)
{cout << e << " ";
}
cout << endl;

在这里插入图片描述

2️⃣erase
删除有三种方式:

删除set中position位置上的元素

void erase ( iterator position )

set<int> s;
s.insert(1);
s.insert(3);
s.insert(5);
s.insert(2);
for (auto& e : s)
{cout << e << " ";
}
cout << endl;
set<int>::iterator pos = s.begin();
s.erase(pos);
for (auto& e : s)
{cout << e << " ";
}

在这里插入图片描述

删除set中值为x的元素,返回删除的元素的个数

size_type erase ( const key_type& x )

set<int> s;
s.insert(1);
s.insert(3);
s.insert(5);
s.insert(2);
for (auto& e : s)
{cout << e << " ";
}
cout << endl;
s.erase(3);
for (auto& e : s)
{cout << e << " ";
}

在这里插入图片描述

删除set中[first, last)区间中的元素

void erase ( iterator first, iterator last )

set<int> s;
s.insert(1);
s.insert(3);
s.insert(5);
s.insert(2);
for (auto& e : s)
{cout << e << " ";
}
cout << endl;
s.erase(s.begin(), s.end());
for (auto& e : s)
{cout << e << " ";
}

在这里插入图片描述

3️⃣swap
交换set中的元素

void swap ( set<Key,Compare,Allocator>& st );

	set<int> s1;s1.insert(1);s1.insert(3);s1.insert(5);for (auto& e : s1){cout << e << " ";//1 3 5}cout << endl;set<int> s2;s2.insert(7);s2.insert(8);s2.insert(6);for (auto& e : s2){cout << e << " "; //6 7 8}cout << endl;s2.swap(s1);for (auto& e : s1){cout << e << " ";//6 7 8}cout << endl;for (auto& e : s2){cout << e << " ";//1 3 5}

4️⃣clear
将set中的元素清空

void clear ( )

set<int> s1;
s1.insert(1);
s1.insert(3);
s1.insert(5);
s1.clear();
for (auto& e : s1)
{cout << e << " ";// 空
}

5️⃣find
找到了,返回set中值为x的元素的位置,如果每找到,返回最后一个元素的下一个位置

iterator find ( const key_type& x ) const

set<int> s1;
s1.insert(1);
s1.insert(3);
s1.insert(5);
//s1.clear();
set<int>::iterator pos = s1.find(3);
if (pos != s1.end())cout << "找到了" << endl;//找到了
elsecout << "没找到" << endl;

6️⃣count
返回set中值为x的元素的个数,因为set是去重的,所以存在返回1,不存在返回0

size_type count ( const key_type& x ) const

set<int> s1;
s1.insert(1);
s1.insert(3);
s1.insert(5);
cout << s1.count(3) << endl;//1
cout << s1.count(33) << endl;//0

3.2 multiset

multiset与set的区别是存储的元素可以重复

void test_set8()
{multiset<int> s;s.insert(1);s.insert(3);s.insert(3);s.insert(5);s.insert(5);s.insert(5);s.insert(2);for (auto& e : s){cout << e << " ";//1 2 3 3 5 5 5}
}

还有接口与set的不同,分别是find和count

set的find与multiset的find
set不能有重复元素,所以找到了返回该元素的位置;multiset有重复元素,找到了返回该元素的第一个的位置。找不到都是返回end()

multiset<int> s;
s.insert(1);
s.insert(3);
s.insert(3);
multiset<int>::iterator pos = s.find(3);//返回第一个3的位置
while (pos != s.end())
{cout << *pos << " ";// 3 3++pos;
}
cout << endl;
}

set的count与multiset的count
set没有重复元素,所以存在的元素返回1,不存在返回0;multiset有重复元素,所以存在返回该元素的个数,不存在返回0

multiset<int> s;
s.insert(1);
s.insert(3);
s.insert(3);
s.insert(3);
s.insert(3);
cout << s.count(3) << endl;//4

3.3 map

与sert一样,map可以使容器的元素有序且去重
特点:

  1. map中的元素是键值对,由key和value组成
  2. 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair—— typedef pair<const key, T> value_type;
  3. 在内部,map中的元素总是按照键值key进行比较排序的
  4. map中的key是唯一的,并且不能修改
  5. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
  6. map支持下标访问符,可以进行插入、查找和修改
  7. map的底层为平衡搜索树(红黑树)

3.3.1 模板参数列表

在这里插入图片描述

  • key: 键值对中key的类型
  • T: 键值对中value的类型
  • Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
  • Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器

3.3.2 构造

1️⃣构造空的map

map<string, string> m;

2️⃣用迭代器区间进行构造

map<string, string> m1(m.begin(), m.end());

3️⃣拷贝构造

map<string, string> m2(m);

3.3.3 迭代器

1️⃣begin和end
正向遍历

map<string, string> m;
m.insert(pair<string, string>("sort", "排序"));
m.insert(pair<string, string>("apple", "苹果"));
m.insert(pair<string, string>("left", "左边"));
map<string, string>::iterator it = m.begin();
while (it != m.end())
{cout << *it << " ";//错误写法,编译报错++it;
}

因为map的每个元素是键值对,由key和value组成,即pair,而且它们的类型不一定相同,所以要用 . 或者 -> 指向对应的成员

map<string, string> m;
m.insert(pair<string, string>("sort", "排序"));
m.insert(pair<string, string>("sort", "排序"));
m.insert(pair<string, string>("sort", "排序"));
m.insert(pair<string, string>("apple", "苹果"));
m.insert(pair<string, string>("left", "左边"));
map<string, string>::iterator it = m.begin();
while (it != m.end())
{//cout << (*it).first << ":" << (*it).second << endl;cout << it->first << ":" << it->second << endl;++it;
}

在这里插入图片描述

2️⃣rbegin和rend
反向遍历

map<string, string>::reverse_iterator rit = m.rbegin();
while (rit != m.rend())
{//cout << (*rit).first << ":" << (*rit).second << endl;cout << rit->first << ":" << rit->second << endl;++rit;
}

在这里插入图片描述

3.3.4 容量

1️⃣empty
检测map中的元素是否为空,是返回true,否则返回false

map<string, string> m;
cout << m.empty() << endl;//1

2️⃣size
返回map中有效元素的个数

m.insert(pair<string, string>("left", "左边"));
cout << m.size() << endl;//1

3.3.5 修改操作

1️⃣insert

pair<iterator,bool> insert ( const value_type& x )

在map中插入的是键值对,返回值也是键值对,如果插入成功,则返回当前元素(键值对)的位置和true,插入失败,则返回原来已有的元素的位置和false

插入的方式有三种写法:

map<string, string> m;
m.insert(pair<string, string>("sort", "排序"));//C++98
m.insert(make_pair("apple", "苹果"));//C++98
m.insert({ "left", "左边" }); //C++11 多参数隐式类型转换

在这里插入图片描述

2️⃣erase
删除有3种方式,与set相同:

删除position位置上的元素

void erase ( iterator position )

map<string, string> m;
m.insert(make_pair("sort", "排序"));
m.insert(make_pair("apple", "苹果"));
m.insert(make_pair("left", "左边"));
for (auto& e : m)
{cout << e.first << ":" << e.second << " ";
}
cout << endl;
map<string, string>::iterator pos = m.begin();
m.erase(pos);
for (auto& e : m)
{cout << e.first << ":" << e.second << " ";
}

在这里插入图片描述

删除键值为x的元素

size_type erase ( const key_type& x )

m.erase("sort");

在这里插入图片描述

删除[first, last)区间中的元素

void erase ( iterator first, iterator last )

m.erase(m.begin(), m.end());

3️⃣swap
交换两个map中的元素

void swap ( map<Key,T,Compare,Allocator>& mp )

map<string, string> m1;
m1.insert(make_pair("sort", "排序"));
m1.insert(make_pair("apple", "苹果"));
for (auto& e : m1)
{cout << e.first << ":" << e.second << " ";
}
map<string, string> m2;
m2.insert(make_pair("left", "左边"));
m2.insert(make_pair("right", "右边"));
for (auto& e : m2)
{cout << e.first << ":" << e.second << " ";
}
m2.swap(m1);
for (auto& e : m1)
{cout << e.first << ":" << e.second << " ";
}
for (auto& e : m2)
{cout << e.first << ":" << e.second << " ";
}

在这里插入图片描述

4️⃣clear
将map中的元素清空

void clear ( )

map<string, string> m;
m.insert(make_pair("sort", "排序"));
m.clear();
cout << m.empty() << endl;//1

5️⃣find
查找key为x的元素,找到了返回该元素的迭代器,找不到返回end

iterator find ( const key_type& x )

map<string, string> m;
m.insert(make_pair("sort", "排序"));
map<string, string>::iterator pos = m.find("sort");
if (pos != m.end())cout << "找到了" << endl;//找到了
elsecout << "没找到" << endl;

6️⃣count
返回key为x在map中的个数,由于map会去重,所以存在返回1,不存在返回0

size_type count ( const key_type& x ) const

map<string, string> m;
m.insert(make_pair("sort", "排序"));
m.insert(make_pair("sort", "排序"));
cout << m.count("sort") << endl;//1
cout << m.count("apple") << endl;//0

3.3.6 operator[]

mapped_type& operator[] (const key_type& k);

该函数的参数是key,返回值是value。可以用来插入、查找、修改和计数。先来看看使用:

1️⃣插入:如果key没有重复,插入成功

map<string, string> m;
m.insert(make_pair("sort", "排序"));
m["left"];//插入
for (auto& e : m)
{cout << e.first << ":" << e.second << endl;
}

在这里插入图片描述

2️⃣查找:插入的key已经存在,查找到该key对应的value

map<string, string> m;
m.insert(make_pair("sort", "排序"));
m.insert(make_pair("apple", "苹果"));
cout << m["apple"] << endl;//苹果

3️⃣修改:插入的key已经存在,同时右边如下代码所示,将该key对应的value修改

map<string, string> m;
m.insert(make_pair("sort", "排序"));
m.insert(make_pair("apple", "苹果"));
m["sort"] = "排序的英文";
for (auto& e : m)
{cout << e.first << ":" << e.second << endl;
}

在这里插入图片描述

4️⃣插入+修改:插入key没有重复,且右边如下代码所示,修改对应的value(其实是补上)

map<string, string> m;
m.insert(make_pair("sort", "排序"));
m.insert(make_pair("apple", "苹果"));
m["left"] = "左边";
for (auto& e : m)
{cout << e.first << ":" << e.second << endl;
}

在这里插入图片描述

5️⃣统计次数

map<string, int> m;
string arr[] = { "sort","sort" ,"apple" ,"apple", "banana","one" };
for (auto& e : arr)
{m[e]++;
}
for (auto& e : m)
{cout << e.first << ":" << e.second << " ";cout << endl;
}

在这里插入图片描述

接下来看看operator[]是如何实现以上操作的:
在这里插入图片描述

operator[]内部其实调用了insert函数
在这里插入图片描述
我们再来看看insert函数:
在这里插入图片描述
回顾下,insert函数的要插入的数据类型是键值对
在这里插入图片描述
它的返回类型也是键值对,operator[]调用insert函数得到的返回值是迭代器,对迭代器解引用然后点访问迭代器的第二个成员,最后返回该成员。

梳理下:
首先看operator[]调用insert函数,而insert里面的make_pair是(k, mapped_type()),也就是说key值是要输入的,而value我们不写编译器帮我们默认构造出来,int类型是0。接着insert函数就要返回了,返回的是键值对,插入成功,返回该位置的迭代器和true;插入失败,返回该位置的迭代器和false。.first,得到返回值的第一个成员,即迭代器。迭代器的本质是指针,指针指向的是该位置的key和对应的value,解引用指针,然后最后的 .second 得到是该迭代器的value,即插入的key对应的value

3.4 multimap

multimap与map的区别和multiset与set的区别相同,都能形成有序,但是multimap可以允许元素重复

multimap<string, string> m;
m.insert(make_pair("sort", "排序"));
m.insert(make_pair("sort", "排序"));
m.insert(make_pair("left", "左边"));
m.insert(make_pair("sort", "排序"));
m.insert(make_pair("apple", "苹果"));
m.insert(make_pair("apple", "苹果"));
for (auto& e : m)
{cout << e.first << ":" << e.second << " ";cout << endl;
}

在这里插入图片描述

还有find和count:

map的find与multimap的find
map返回该元素的迭代器,multimap返回该元素的第一个的迭代器

multimap<string, string> m;
m.insert(make_pair("sort", "排序"));
m.insert(make_pair("sort", "排序"));
m.insert(make_pair("apple", "苹果"));
multimap<string, string>::iterator pos = m.find("sort");
while (pos != m.end())
{cout << pos->first << ":" << pos->second << endl;++pos;
}

在这里插入图片描述

map的count与multimap的count
map没有重复元素,所以该元素存在返回1,不存在返回0;multimap可以有重复元素,存在返回该元素的个数,不存在返回0

multimap<string, string> m;
m.insert(make_pair("sort", "排序"));
m.insert(make_pair("sort", "排序"));
m.insert(make_pair("apple", "苹果"));
cout << m.count("sort") << endl;//2
cout << m.count("apple") << endl;//1
cout << m.count("left") << endl;//0

相关文章:

【C++】set、multiset与map、multimap的使用

目录 一、关联式容器二、键值对三、树形结构的关联式容器3.1 set3.1.1 模板参数列表3.1.2 构造3.1.3 迭代器3.1.4 容量3.1.5 修改操作 3.2 multiset3.3 map3.3.1 模板参数列表3.3.2 构造3.3.3 迭代器3.3.4 容量3.3.5 修改操作3.3.6 operator[] 3.4 multimap 一、关联式容器 谈…...

Matlab/simulink微电网的PQ控制和下垂控制无缝切换建模仿真

​...

外包干了6个月,技术退步明显

先说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...

3. springboot中集成部署vue3

1. vue3构建 构建命令 npm run build&#xff0c; 构建的结果在disc目录&#xff1a; 2. springboot集成 2.1 拷贝vue3构建结果到springboot resources/static目录 2.2 springboot pom依赖 添加thymeleaf依赖 <dependency><groupId>org.springframework.boot</…...

问题

今天遇到数组开太大问题&#xff1a; 数组放在main函数里面&#xff0c;表示该数组是局部变量&#xff0c;不是全局变量&#xff0c;所以该数组是开在栈上&#xff0c;而栈的空间往往比较小&#xff0c;所以二维数组定义太大会导致爆栈。 全局变量全部存储在静态存储区。 在…...

#WEB前端

1.实验&#xff1a;vscode安装&#xff0c;及HTML常用文本标签 2.IDE&#xff1a;VSCODE 3.记录&#xff1a; &#xff08;1&#xff09;网页直接搜索安装vscode &#xff08;2&#xff09;打开vscode&#xff0c;在下图分别安装以下插件&#xff1a; Html Css Support …...

c语言经典测试题9

1.题1 #include <stdio.h> int main() { int i 1; sizeof(i); printf("%d\n", i); return 0; } 上述代码运行结果是什么呢&#xff1f; 我们来分析一下&#xff1a;其实这题的难点就是sizeof操作后i的结果是否会改变&#xff0c;首先我们创建了一个整型i&a…...

3d 舞蹈同步

目录 看起来很强大 unity驱动bvh跳舞&#xff1a; 脚飘动问题&#xff1a; bvh和播放关节对应关系 zxy格式 bvh和播放关节对应关系 zyx的对应关系&#xff1a; bvh播放器&#xff1a; 看起来很强大 GitHub - FORTH-ModelBasedTracker/MocapNET: We present MocapNET, a …...

win环境nginx实战配置详解

项目中经常使用nginx做负载均衡&#xff0c;接口路由、文件、文档的上传及下载、视频的代理播放等等&#xff0c;都离不开nginx的支持&#xff0c;今天我们分享一下其个使用场景。 1、配置文件 nd-nginx.conf 全局配置 #全局配置端&#xff0c;对全局生效&#xff0c;主要设置…...

数字化转型导师坚鹏:如何制定证券公司数字化转型年度培训规划

如何制定与实施证券公司数字化转型年度培训规划 ——以推动证券公司数字化转型战略落地为核心&#xff0c;实现知行果合一 课程背景&#xff1a; 很多证券公司都在开展数字化转型培训工作&#xff0c;目前存在以下问题急需解决&#xff1a; 缺少针对性的证券公司数字化转型…...

新王炸:文生视频Sora模型发布,能否引爆AI芯片热潮

前言 前方高能预警&#xff0c;Sora来袭&#xff01; 浅析Sora的技术亮点 语言模型中构建关键词联系 视频素材分解为时空碎片 扩散模型DiT Not for play, But change world! OpenAI的宏大目标 未来已来&#xff0c;只是尚未流行 Sora的成本与OpenAI的7万亿美金豪赌 算…...

代码随想录算法训练营|day48

第九章 动态规划 121.买卖股票的最佳时机122.买卖股票的最佳时机II代码随想录文章详解 121.买卖股票的最佳时机 本题中股票只能买卖一次 dp[i][0] 表示第i天不买入股票持有的最大现金&#xff1b;dp[i][1] 表示第i天买入股票持有的最大现金。 不买股票持有的最大现金买入股票…...

架构面试题汇总:并发和锁(三)

在现代软件开发中&#xff0c;并发编程和多线程处理已成为不可或缺的技能。Java作为一种广泛使用的编程语言&#xff0c;提供了丰富的并发和多线程工具&#xff0c;如锁、同步器、并发容器等。因此&#xff0c;对于Java开发者来说&#xff0c;掌握并发编程和多线程处理的知识至…...

蓝桥杯(3.2)

1209. 带分数 import java.io.*;public class Main {static BufferedReader br new BufferedReader(new InputStreamReader(System.in));static PrintWriter pw new PrintWriter(new OutputStreamWriter(System.out));static final int N 10;static int n, cnt;static int[…...

[数据集][目标检测]鸟类检测数据集VOC+YOLO格式11758张200类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;11758 标注数量(xml文件个数)&#xff1a;11758 标注数量(txt文件个数)&#xff1a;11758 标…...

YOLOv9:使用可编程梯度信息学习您想学习的内容

摘要 arxiv.org/pdf/2402.13616.pdf 当今的深度学习方法侧重于如何设计最合适的目标函数,以便模型的预测结果能最接近于实际结果。同时,还必须设计一个适当的架构,以便于获取足够的预测信息。现有的方法忽略了一个事实,即当输入数据经历层层特征提取和空间变换时,会损失…...

uniapp:使用DCloud的uni-push推送消息通知(在线模式)java实现

uniapp:使用DCloud的uni-push推送消息通知&#xff08;在线模式&#xff09;java实现 1.背景 今天开发app的时候遇到一个需求&#xff1a; 业务在出发特定条件的时候向对应的客户端推送消息通知。 为什么选择在线模式&#xff0c;因为我们使用的是德邦类似的手持终端&#xf…...

【简说八股】面试官:你知道什么是AOP么?

回答 AOP(Aspect-Oriented Programming)&#xff0c;即面向切面编程&#xff0c;是一种编程范式&#xff0c;它的主要思想是将应用程序中的横切关注点&#xff08;如日志记录、性能统计、安全控制等&#xff09;从业务逻辑中剥离出来&#xff0c;然后通过特殊的方式将这些横切…...

ASUS华硕天选5笔记本电脑FX607JV原装出厂Win11系统下载

ASUS TUF Gaming F16 FX607JV天选五原厂Windows11系统 适用型号&#xff1a; FX607JU、FX607JI、FX607JV、 FX607JIR、FX607JVR、FX607JUR 下载链接&#xff1a;https://pan.baidu.com/s/1l963wqxT0q1Idr98ACzynQ?pwd0d46 提取码&#xff1a;0d46 原厂系统自带所有驱动、…...

Unity(第二十一部)动画的基础了解(感觉不了解其实也行)

1、动画组件老的是Animations 动画视频Play Automatically 是否自动播放Animate Physics 驱动方式&#xff0c;勾选后是物理驱动Culling Type 剔除方式 默认总是动画化就会一直执行下去&#xff0c;第二个是基于渲染播放&#xff08;离开镜头后不执行&#xff09;&#xff0c; …...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...