【STL】 set 与 multiset:基础、操作与应用

在 C++ 标准库中,set 和 multiset 是两个非常常见的关联容器,主要用于存储和管理具有一定规则的数据集合。本文将详细讲解如何使用这两个容器,并结合实例代码,分析其操作和特性。

0.基础操作概览

0.1.构造:

set<T> st;                   
// 默认构造函数:

set(const set& st);          
//拷贝构造函数

0.2.赋值:

set& operator=(const set& st); 
//重载等号操作符

0.3.统计set容器大小以及交换set容器

size();                       
//返回容器中元素的数目

empty();                       
//判断容器是否为空

swap(st);                     
 //交换两个集合容器

0.4.set容器进行插入数据和删除数据

insert(elem);                  
//在容器中插入元素。      

clear();                       
// 清除所有元素
erase(pos);                         
//删除pos迭代器所指的元素,返回下一个元素的迭代器。

erase(beg, end);                   
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。

erase(elem);                       
//删除容器中值为elem的元素。

0.5.set查找和统计:对set容器进行查找数据以及统计数据

find(key);          
//查找key是否存在,若存在,返回该键的元素的迭代器;
//若不存在,返回set.end();

count(key);                        
//对于set而言,统计key的元素个数
//只有两种结果:如果容器中不存在key,返回0; 否则,返回1

0.6.排序

set<int> st1;               
// 储存int的集合(从小到大)

set<int, greater<int>> st2; 
// 储存int的集合(从大到小)

1. set 与 multiset 的基本概念

  • set:它是一种自动去重且按顺序排列的集合。每次插入元素时,set 会自动判断该元素是否已存在,若存在则不会插入。
  • multiset:允许重复元素的集合,因此可以存储多个相同的元素。
  • 关联容器:关联容器中的元素在插入时自动排序,因此不同于顺序容器如 vector 或 list,不需要手动排序。

2. set 容器的构造与赋值

在 C++ 中,set 提供了多种构造方式:

  • 默认构造set <int> st; 创建一个空的整数集合。
  • 拷贝构造set<int> st2(st); 从已有的集合 st 创建一个副本。
  • 赋值操作set& operator=(const set& st);可以通过重载的 = 操作符将一个集合的内容赋值给另一个集合。

构造与赋值实例:

void test0()
{
    // 1.默认构造
    set<int>s;
    s.insert(1);  // 插入元素1
    s.insert(-4); // 插入元素-4
    s.insert(2);  // 插入元素2
    s.insert(5);  // 插入元素5
    s.insert(8);  // 插入元素8
    s.insert(1);  // 插入重复元素1,自动忽略

    print(s);  // 打印集合中的元素,输出为:-4 1 2 5 8

    cout << endl;
    // 2.拷贝构造
    set<int>s2(s);  // 拷贝构造函数
    print(s2);  // 输出:-4 1 2 5 8

    cout << endl;
    // 3.赋值操作
    set<int>s3 = s2;  // 赋值操作符
    print(s3);  // 输出:-4 1 2 5 8
}

在这里插入图片描述

在此代码中,set 的插入操作可以看出,重复元素(如插入的 1)不会出现在集合中,这是 set 自动去重的特性。

3.遍历 set 容器

在 set 中,不能使用下标访问元素,因此遍历集合有两种常见方式:

  • 使用迭代器遍历:通过迭代器访问集合元素,适合所有关联容器。
  • 基于范围的 for 循环:简化迭代器操作,代码更加简洁。

迭代器遍历:

void print(set<int>& s)
 {
    for (set<int>::iterator it = s.begin(); it != s.end(); it++) 
    {
        cout << *it << " ";  // 输出每个元素
    }
    cout << endl;
    
    /*for (auto it = s.begin(); it != s.end(); it++)
	{
		cout << *it << " ";
	}*/
}

基于范围的 for 循环

void print(set<int>& s) 
{
    for (int elem : s) 
    {
        cout << elem << " ";  // 直接输出元素
    }
    cout << endl;
    
    /*for (auto it : s)
	{
		cout << it << " ";
	}*/
}

降序遍历:如果集合是降序排序的,例如使用
set<int, greater>,需要在定义迭代器时添加相应的比较器。

void print(set<int, greater<int>>& s) 
{
    for (set<int, greater<int>>::iterator it = s.begin(); it != s.end(); it++) 
    {
        cout << *it << " ";  // 输出降序排列的元素
    }
    cout << endl;
}

遍历操作

void test_traversal() 
{
    set<int> s;
    s.insert(5);
    s.insert(1);
    s.insert(3);
    s.insert(7);
    
    cout << "使用迭代器遍历 set:" << endl;
    print(s);  // 输出:1 3 5 7

    cout << "使用基于范围的 for 循环遍历 set:" << endl;
    print2(s);  // 输出:1 3 5 7
}

总结:遍历 set 的两种方式都非常直观,迭代器方式适合所有关联容器,而基于范围的 for 循环则能让代码更简洁。

5. set 容器的大小统计与交换

  • size();返回集合中的元素数量。
  • empty();检查集合是否为空,若为空返回 true,否则返回false。
  • swap();交换两个集合的内容。

统计大小与交换

void test1()
{
	//构造2个有数据的set容器
	set<int>s;
	s.insert(0);
	s.insert(1);
	s.insert(0);
	s.insert(9);
	s.insert(6);
	s.insert(11);
	

	set<int>s1;
	s1.insert(0);
	s1.insert(0);
	s1.insert(0);
	s1.insert(99);
	s1.insert(4);
	s1.insert(-1);


	cout << endl;
	
	//判断是否为空
	if (!s.empty()) 
	{
		cout << "s容器的长度为:" << s.size() << endl;
	}
	

	cout << endl;
	
	//交换
	cout<< "交换前:" << endl;
	cout << "s: " ;
	print(s);
	cout << endl << "s1:";
	print(s1);

	s.swap(s1);

	cout << endl << endl;
	cout << "交换后:" << endl ;
	cout << "s: " ;
	print(s);
	cout << endl << "s1: ";
	print(s1);
}

在这里插入图片描述

通过 swap() 操作,s 和 s1 的内容得到了交换。这样可以有效简化代码,避免使用临时变量来保存集合的内容。

6. set 容器的插入与删除操作

  • insert(elem);向集合中插入元素。由于 set 自动排序,插入元素时不会指定位置。

删除元素有三种方式:

  • erase(pos); 删除pos迭代器所指的元素,返回下一个元素的迭代器。

  • erase(beg, end); 删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。

  • erase(elem); 删除容器中值为elem的元素。

void test2()
{
	set<int>s1;
	s1.insert(100);
	s1.insert(100);
	s1.insert(20);
	s1.insert(0);
	s1.insert(44);
	s1.insert(12);
	s1.insert(666);
	s1.insert(9);

	print(s1);

	cout << endl;
	//删除迭代器指定元素
	s1.erase(s1.begin());//这里删掉的是第一个元素0,因为set容器自动排序
	print(s1);

	cout << endl;
	//删除指定元素
	s1.erase(20);
	print(s1);

	cout << endl;
	//删除迭代器指定区间元素
	s1.erase(s1.begin(), s1.end());
	//等价于清空操作:
	//s1.clear();
	cout <<"当前s1的大小为:" << s1.size() << endl;
}

在这里插入图片描述

在此代码中,我们展示了三种不同的 erase 操作,可以方便地删除单个元素或一组元素。

7. set 容器的查找与统计

find(key);
查找key是否存在,若存在,返回该键的元素的迭代器;
若不存在,返回set.end();

count(key);
对于set而言,统计key的元素个数
只有两种结果:如果容器中不存在key,返回0; 否则,返回1

查找与统计:

void test3()
 {
    set<int>s1;
    s1.insert(1);
    s1.insert(100);
    s1.insert(23);
    s1.insert(0);
    s1.insert(404);
    s1.insert(12);
    s1.insert(999);
    s1.insert(9);

    // 查找元素 404
    auto it = s1.find(404);
    if (it != s1.end()) {
        cout << "找到了元素 404" << endl;  // 输出:找到了元素404
    } else {
        cout << "未找到元素 404" << endl;
    }

    // 使用 count 统计元素个数
    int n = s1.count(404);
    cout << "s1 中元素 404 的个数为:" << n << endl;  // 输出:1
}

通过 find() 和 count() 函数,可以轻松实现元素的查找与存在性检查。

8. set 容器的排序特性

默认情况下,set 按照升序排列。可以通过
set<int, greater<int>> 指定降序排列。

  • set<int> st1; 储存int的集合(从小到大)
  • set<int, greater<int>> st2; 储存int的集合(从大到小)
    排序:
void test4()
{
	//默认构造
	set<int>s1;
	//等价于set<int, less<int>>s1;
	s1.insert(10);
	s1.insert(40);
	s1.insert(20);
	s1.insert(0);
	s1.insert(-10);

	print(s1);

	//降序构造,用到比较器greater(类型)
	cout << endl;
	set<int, greater<int>>s2;
	s2.insert(10);
	s2.insert(40);
	s2.insert(20);
	s2.insert(0);
	s2.insert(-10);

	print2(s2);
}

通过比较器 greater 可以实现集合的降序排列。

整体操作如下:

//set:自动去重 且 按顺序排列的 集合
//multiset:允许重复元素
//关联容器:插入时自动排序
//只能使用迭代器,基于范围的for循环 进行遍历,不能使用下标访问
#include<iostream>
#include<set>
using namespace std;

//1.构造:
//set<T> st;                         // 默认构造函数:
//set(const set& st);                //拷贝构造函数

//2.赋值:
//set& operator=(const set& st);     //重载等号操作符

//3.统计set容器大小以及交换set容器
//size();                            //返回容器中元素的数目
//empty();                           //判断容器是否为空
//swap(st);                          //交换两个集合容器



//4.set容器进行插入数据和删除数据
//insert(elem);                      //在容器中插入元素。      
//clear();                           // 清除所有元素

//erase(pos);                        //删除pos迭代器所指的元素,返回下一个元素的迭代器。
//erase(beg, end);                   //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
//erase(elem);                       //删除容器中值为elem的元素。



//5.set查找和统计:对set容器进行查找数据以及统计数据
//find(key);                         //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
//count(key);                        //对于set而言,统计key的元素个数:只有两种结果:0和1,如果容器中不存在key,返回0; 否则,返回1
	
  

//6.排序
//set<int> st1;               // 储存int的集合(从小到大)
//set<int, greater<int>> st2; // 储存int的集合(从大到小)

//遍历set容器(用迭代器,基于范围for循环)
void print(set<int>& s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << " ";
	}


	/*for (auto it = s.begin(); it != s.end(); it++)
	{
		cout << *it << " ";
	}*/

	/*for (auto it : s)
	{
		cout << it << " ";
	}*/

}

//遍历降序set容器
//注意:如果是降序set容器,在传参,定义迭代器时,都要加上比较器:greater<int>
void print2(set<int,greater<int>>& s)
{
	for (set<int,greater<int>>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << " ";
	}


	/*for (auto it = s.begin(); it != s.end(); it++)
	{
		cout << *it << " ";
	}*/

	/*for (auto it : s)
	{
		cout << it << " ";
	}*/
}



//1.构造与赋值
void test0()
{
	// 1.默认构造
	set<int>s;
	s.insert(1);  // 插入元素1
	s.insert(-4); // 插入元素-4
	s.insert(2);  // 插入元素2
	s.insert(5);  // 插入元素5
	s.insert(8);  // 插入元素8
	s.insert(1);  // 插入重复元素1,自动忽略

	print(s);  // 打印集合中的元素,输出为:-4 1 2 5 8

	cout << endl;
	// 2.拷贝构造
	set<int>s2(s);  // 拷贝构造函数
	print(s2);  // 输出:-4 1 2 5 8

	cout << endl;
	// 3.赋值操作
	set<int>s3 = s2;  // 赋值操作符
	print(s3);  // 输出:-4 1 2 5 8
}

//2.统计set容器大小以及交换set容器
void test1()
{
	//构造2个有数据的set容器
	set<int>s;
	s.insert(0);
	s.insert(1);
	s.insert(0);
	s.insert(9);
	s.insert(6);
	s.insert(11);
	

	set<int>s1;
	s1.insert(0);
	s1.insert(0);
	s1.insert(0);
	s1.insert(99);
	s1.insert(4);
	s1.insert(-1);


	
	//判断是否为空
	if (!s.empty()) 
	{
		cout << "s容器的长度为:" << s.size() << endl;
	}
	

	cout << endl;
	
	//交换
	cout<< "交换前:" << endl;
	cout << "s: " ;
	print(s);
	cout << endl << "s1:";
	print(s1);

	s.swap(s1);

	cout << endl << endl;
	cout << "交换后:" << endl ;
	cout << "s: " ;
	print(s);
	cout << endl << "s1: ";
	print(s1);
}





//3.set容器进行插入数据和删除数据
void test2()
{
	set<int>s1;
	s1.insert(100);
	s1.insert(100);
	s1.insert(20);
	s1.insert(0);
	s1.insert(44);
	s1.insert(12);
	s1.insert(666);
	s1.insert(9);

	print(s1);

	cout << endl;
	//删除迭代器指定元素
	s1.erase(s1.begin());//这里删掉的是第一个元素0,因为set容器自动排序
	print(s1);

	cout << endl;
	//删除指定元素
	s1.erase(20);
	print(s1);

	cout << endl;
	//删除迭代器指定区间元素
	s1.erase(s1.begin(), s1.end());
	//等价于清空操作:
	//s1.clear();
	cout <<"当前s1的大小为:" << s1.size() << endl;
}


//4.set查找和统计:对set容器进行查找数据以及统计数据
void test3()
{
	set<int>s1;
	s1.insert(1);
	s1.insert(100);
	s1.insert(23);
	s1.insert(0);
	s1.insert(404);
	s1.insert(12);
	s1.insert(999);
	s1.insert(9);


	//查找:返回迭代器
	//set<int>::iterator it = s1.find(404);
	//用auto更方便
	auto it = s1.find(404);
	
	if (it != s1.end())
	{
		cout << "找到了" << endl;
	}
	else
	{
		cout << "没找到" << endl;
	}

	//统计个数,也可以用来查找
	int n = s1.count(404);
	if (n)
	{
		cout << "找到了" << endl;
	}
	else
	{
		cout << "没找到" << endl;
	}
	cout <<"s1中404的个数为:" << n << endl;
}



//5.set容器的指定排序:默认从小到大排序
void test4()
{
	//默认构造
	set<int>s1;
	//等价于set<int, less<int>>s1;
	s1.insert(10);
	s1.insert(40);
	s1.insert(20);
	s1.insert(0);
	s1.insert(-10);

	print(s1);

	//降序构造,用到比较器greater(类型)
	cout << endl;
	set<int, greater<int>>s2;
	s2.insert(10);
	s2.insert(40);
	s2.insert(20);
	s2.insert(0);
	s2.insert(-10);

	print2(s2);




}

int main()
{
	test0();
	test1();
	test2();
	test3();
	test4();
	return 0;
}

9.相关注意事项

9.1. 自动排序与元素唯一性

自动排序:set 会自动将插入的元素按升序(或根据提供的自定义比较器排序)进行排序。因此,插入顺序与实际存储顺序可能不同。

注意:由于 set 是自动排序的容器,插入操作可能会引发排序操作,这使得插入操作的平均时间复杂度为 O(log n),适合需要快速查找和去重的场景。

元素唯一性:set 不允许重复元素。如果插入的元素已经存在于集合中,set 会自动忽略该元素。即使多次插入相同的值,集合中只会保留一个副本。

set<int> s;
s.insert(1);
s.insert(1);  // 插入重复元素,set 会自动忽略
print(s);     // 输出:1

9.2. 不能使用下标访问

与 vector 不同,set 作为关联容器不能通过下标访问元素,也不能像顺序容器那样直接修改元素。只能通过迭代器或基于范围的 for 循环来遍历集合。

set<int> s = {10, 20, 30};
// s[0] = 5;  // 错误!set 不能使用下标
for (int elem : s) 
{
    cout << elem << " ";  // 正确的遍历方式
}

9.3. 修改元素的限制

在 set 中,由于其自动排序的特性,不能直接通过迭代器修改元素的值如果需要修改元素值,必须先删除该元素,然后插入新的值。

set<int> s = {10, 20, 30};
auto it = s.find(20);
if (it != s.end()) 
{
    s.erase(it);     // 先删除 20
    s.insert(25);    // 再插入新值 25
}
print(s);  // 输出:10 25 30

9.4. 迭代器的有效性

当删除或插入元素时,set 的迭代器可能会失效。特别是在删除操作中,如果需要使用迭代器操作,建议在删除之后重新获取下一个有效的迭代器。

set<int> s = {1, 2, 3, 4, 5};
auto it = s.begin();
while (it != s.end()) 
{
    if (*it == 3) 
    {
        it = s.erase(it);  // erase 返回下一个有效迭代器
    } 
    else 
    {
        it++;
    }
}
print(s);  // 输出:1 2 4 5

9.6. 自定义排序规则

如果需要按自定义顺序排序 set 中的元素,可以通过传入自定义的比较器来改变排序方式。例如,可以使用 greater 来实现降序排列,或者提供自定义的比较函数。

set<int, greater<int>> s = {10, 20, 30};
print2(s);  // 输出:30 20 10

9.8. 避免重复调用 find 和 count

如果你想要同时查找元素和统计某个元素的出现次数,不必重复调用 find() 和 count(),因为 count() 可以直接返回是否存在目标元素(对于 set,返回值只会是 0 或 1)。count() 本质上相当于 find() 的简化版。

set<int> s = {10, 20, 30};
if (s.count(20)) 
{
    cout << "元素 20 存在" << endl;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/881899.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决nginx代理SSE接口的响应没有流式返回

目录 现象原来的nginx配置解决 现象 前后端分离的项目&#xff0c;前端访问被nginx反向代理的后端SSE接口&#xff0c;预期是流式返回&#xff0c;但经常是很久不响应&#xff0c;一响应全部结果一下子都返回了。查看后端项目的日志&#xff0c;响应其实是流式产生的。推测是n…

【BurpSuite】Cross-site scripting (XSS 学徒部分:1-9)

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【BurpSuite】Cross-site scripting (XSS 学徒部分:1-9&#xff09; 实验一 Lab: Reflected XSS into HTML context with nothing…

[Redis] 渐进式遍历+使用jedis操作Redis+使用Spring操作Redis

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

javase复习day30综合练习

制造假数据 制造数据 练习一 package Demo1;import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; im…

react hooks--React.memo

基本语法 React.memo 高阶组件的使用场景说明&#xff1a; React 组件更新机制&#xff1a;只要父组件状态更新&#xff0c;子组件就会无条件的一起更新。 子组件 props 变化时更新过程&#xff1a;组件代码执行 -> JSX Diff&#xff08;配合虚拟 DOM&#xff09;-> 渲…

数据结构:二叉树OJ题(基础版)

前言 更完两期二叉树的知识之后&#xff0c;来做几道oj题巩固一下基础 一、翻转二叉树 链接&#xff1a;leetcode链接 还是分治思想&#xff0c;将问题分解成左子树和右子树交换&#xff0c;遇到空树停止 采用递归算法做题 TreeNode* invertTree(TreeNode* root) {if(root …

Golang | Leetcode Golang题解之第409题最长回文串

题目&#xff1a; 题解&#xff1a; func longestPalindrome(s string) int {mp : map[byte]int{}for i : 0; i < len(s); i {mp[s[i]]}res : 0for _, v : range mp {if v&1 1 {res v - 1} else {res v}}if res<len(s) {res}return res }

华为HarmonyOS地图服务 3 - 如何开启和展示“我的位置”?

一. 场景介绍 本章节将向您介绍如何开启和展示“我的位置”功能&#xff0c;“我的位置”指的是进入地图后点击“我的位置”显示当前位置点的功能。效果如下&#xff1a; 二. 接口说明 “我的位置”功能主要由MapComponentController的方法实现&#xff0c;更多接口及使用方法…

基于51单片机的手环设计仿真

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52单片机&#xff0c;DHT11温湿度采集温湿度&#xff0c;滑动变阻器连接ADC0832数模转换器模拟水位传感器检测水位&#xff0c;通过LCD1602显示信息&#xff0c;然后在程序里设置好是否…

JavaEE: 创造无限连接——网络编程中的套接字

文章目录 Socket套接字TCP和UDP的区别有连接/无连接可靠传输/不可靠传输面向字节流/面向数据报全双工/半双工 UDP/TCP api的使用UDPDatagramSocketDatagramPacketInetSocketAddress练习 TCPServerSocketSocket练习 Socket套接字 Socket是计算机网络中的一种通信机制&#xff0…

代码随想录算法训练营第五十八天 | 拓扑排序精讲-软件构建

目录 软件构建 思路 拓扑排序的背景 拓扑排序的思路 模拟过程 判断有环 写代码 方法一&#xff1a; 拓扑排序 软件构建 题目链接&#xff1a;卡码网&#xff1a;117. 软件构建 文章讲解&#xff1a;代码随想录 某个大型软件项目的构建系统拥有 N 个文件&#xff0c;文…

机器人的动力学——牛顿欧拉,拉格朗日,凯恩

机器人的动力学推导方法有很多&#xff0c;常用得有牛顿&#xff0c;拉格朗日&#xff0c;凯恩等方法&#xff0c;接下来&#xff0c;简单说说他们之间的使用。注&#xff1a;这里不考虑怎么来的&#xff0c;只说怎么应用。 参考1&#xff1a;4-14动力学分析方法-牛顿—欧拉方…

聚焦API安全未来,F5打造无缝集成的解决方案

研究发现&#xff0c;目前超过90%的基于Web的网络攻击都以API端点为目标。随着对API使用需求的增加&#xff0c;这些攻击还会持续增长。现代企业需要一种动态防御策略&#xff0c;在风险升级成代价高昂、令人警惕且往往无法预防的API安全漏洞之前&#xff0c;发现并降低风险。 …

数据库提权【笔记总结】

文章目录 UDF提权以有webshell只有数据库权限条件复现msf工具sql语句提权 MOF提权前言条件复现msf工具php脚本提权 sqlserver提权前言条件xp_cmdshell提权复现 沙盒提权介绍复现 Oracle提权靶场搭建执行任意命令复现 通过注入存储过程提权&#xff08;低权限提升至DBA&#xff…

C++从入门到起飞之——多态 全方位剖析!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 目录 1. 多态的概念 2. 多态的定义及实现 2.1 多态的构成条件 2.1.1 实现多态还有两个必须重要条件&…

群晖NAS使用Docker本地部署网页版Ubuntu系统并实现无公网IP远程访问

文章目录 前言1. 下载Docker-Webtop镜像2. 运行Docker-Webtop镜像3. 本地访问网页版Linux系统4. 群晖NAS安装Cpolar工具5. 配置异地访问Linux系统6. 异地远程访问Linux系统7. 固定异地访问的公网地址 前言 本文旨在详细介绍如何在群晖NAS部署docker-webtop&#xff0c;并结合c…

通用接口开放平台设计与实现——(31)API服务线程安全问题确认与修复

背景 在本系列的前面一篇博客评论中&#xff0c;有小伙伴指出&#xff0c;API服务存在线程安全问题&#xff1a; https://blog.csdn.net/seawaving/article/details/122905199#comments_34477405 今天来确认下&#xff0c;线程是否安全&#xff1f;如不安全&#xff0c;如何…

高配小主机加装SSD固态硬盘,我选择性能与设计兼备的希捷酷鱼 530

高配小主机加装SSD固态硬盘&#xff0c;我选择性能与设计兼备的希捷酷鱼 530 哈喽小伙伴们好&#xff0c;我是Stark-C~ 我最近入手了零刻的一款新发布的 GTi12 Ultra高性能迷你主机&#xff0c;其出色的配置与强大的功能让我有了将它用作主力机的打算。不过因为它的高配版本搭…

【记录一下VMware上开虚拟端口映射到公网】

材料 win11 和装在vmware上的ubuntu 步骤一在Ubuntu上配置静态地址&#xff0c;配置如下 vim /etc/netplan/01-network-manager-all.yaml(此文件看系统上对应的是哪个文件&#xff0c;建议先备份)network:version: 2renderer: NetworkManagerethernets:ens33:dhcp4: falseadd…

四十一、完成内容添加功能(使用go测试方法)

目录 一、添加model 二、完成相关dao 三、使用测试类进行测试 1、把光标防止要测试的方法上&#xff0c;右击并选择 2、自动会生成一个以dao文件加_test命名的文件 3、在其中完善方法并完成测试 四、完成content_create_handle 一、添加model 按数据库字段以及字段格式完…