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

简述C++map容器

pair键值对

std::pair在很多关联容器(如std::mapstd::multimapstd::setstd:multiset等)中被广泛应用。以std::map为例,std::map是一个键值对的容器,其中每个元素都是一个std::pair,键用于唯一标识元素,值则是与键相关联的数据。

pair是类模板,一般用于表示key/value数据,其实现是结构体。

pair结构模板的定义如下:

template <class T1, class T2>

struct pair

{

    T1 first;     // 第一个成员,一般表示key。

    T2 second;  // 第二个成员,一般表示value。

      pair();       // 默认构造函数。

      pair(const T1 &val1,const T2 &val2);   // 有两个参数的构造函数。

      pair(const pair<T1,T2> &p);           // 拷贝构造函数。

      void swap(pair<T1,T2> &p);           // 交换两个pair。

};

make_pair函数模板的定义如下:

template <class T1, class T2>

make_pair(const T1 &first,const T2 &second)

{

      return pair<T1,T2>(first, second);

}

示例代码:

#include <iostream>
#include<utility>using  namespace std;template <class T1, class T2>
struct Pair
{T1 first;        // 第一个成员,一般表示key。T2 second;  // 第二个成员,一般表示value。Pair() {cout << "调用了有默认的构造函数。\n";}Pair(const T1& val1, const T2& val2) :first(val1), second(val2) {cout << "调用了有两个参数的构造函数。\n";}Pair(const Pair<T1, T2>& p) : first(p.first), second(p.second) {cout << "调用了拷贝构造函数。\n";}
};template <class T1, class T2>
Pair<T1, T2> make_Pair(const T1& first, const T2& second)
{// Pair<T1, T2> p(first, second);// return p;        // 返回局部对象。return Pair<T1, T2>(first, second);  // 返回临时对象。
}int main()
{pair<int, string> p0;cout << "p0 first=" << p0.first << ",second=" << p0.second << endl;pair<int, string> p1(1, "吴彦祖");    // 两个参数的构造函数。cout << "p1 first=" << p1.first << ",second=" << p1.second << endl;pair<int, string> p2 = p1;             // 拷贝构造。cout << "p2 first=" << p2.first << ",second=" << p2.second << endl;p2.swap(p0);cout << "p0 first=" << p0.first << ",second=" << p0.second << endl;cout << "p2 first=" << p2.first << ",second=" << p2.second << endl;auto p3 = make_pair(2, "陈冠希");cout << "键:" << p3.first << ", 值:" << p3.second << endl;
}

运行结果: 

map容器

map 容器封装了红黑树(平衡二叉排序树),用于查找。

包含头文件: #include<map>

map容器的元素是pair键值对。

迭代器是双向迭代器。

map类模板的声明:

template <class K, class V, class P = less<K>, class _Alloc = allocator<pair<const K, V >>>

class map : public _Tree<_Tmap_traits< K, V, P, _Alloc, false>>

{

   …

}

第一个模板参数K:key的数据类型(pair.first)。

第二个模板参数V:value的数据类型(pair.second)。

第三个模板参数P:排序方法,缺省按key升序。

第四个模板参数_Alloc:分配器,缺省用new和delete。

map提供了双向迭代器。

二叉链表:                               

struct BTNode                       

{                                 

   pair<K,V> p;       // 键值对。      

      BTNode *parent;   // 父节点。   

      BTNode *lchirld;    // 左子树。

      BTNode *rchild;    // 右子树。

};                                     

一、构造函数

1)map();  // 创建一个空的map容器。

2)map(initializer_list<pair<K,V>> il); // 使用统一初始化列表。

3)map(const map<K,V>& m);  // 拷贝构造函数。

4)map(Iterator first, Iterator last);  // 用迭代器创建map容器。

5)map(map<K,V>&& m);  // 移动构造函数(C++11标准)。

二、特性操作

size_t size() const;        // 返回容器的实际大小(已使用的空间)。

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

void clear();             // 清空容器。

三、元素操作

V &operator[](K key);             // 用给定的key访问元素。

const V &operator[](K key) const;  // 用给定的key访问元素,只读。

V &at(K key);                     // 用给定的key访问元素。

const V &at(K key) const;         // 用给定的key访问元素,只读。

注意:

1)[ ]运算符:如果指定键不存在,会向容器中添加新的键值对;如果指定键不存在,则读取或修改容器中指定键的值。

2)at()成员函数:如果指定键不存在,不会向容器中添加新的键值对,而是直接抛出out_of_range 异常。

示例代码:

#include <iostream>
#include <map>
using  namespace std;int main()
{map<string, string> m({ { "08","冠希" }, { "03","于晏" }, { "01","彦祖" }, { "07","德华" }, { "05","学友" } });cout << "m[08]=" << m["08"] << endl;     // 显示key为08的元素的value。cout << "m[09]=" << m["09"] << endl;    // 显示key为09的元素的value。key为09的元素不存在,将添加新的键值对。cout << "m.at(03)=" << m.at("03") << endl;//m.at("099");错误!!m["07"] = "黎明";                                          // 把key为07的元素的value修改为黎明。m["12"] = "富城";                                          // 将添加新的键值对。for (auto& val : m)cout << val.first << "," << val.second << "  ";cout << endl;
}

运行结果:

四、赋值操作

给已存在的容器赋值,将覆盖容器中原有的内容。

1)map<K,V> &operator=(const map<K,V>& m);         // 把容器m赋值给当前容器。

2)map<K,V> &operator=(initializer_list<pair<K,V>> il);  // 用统一初始化列表给当前容器赋值。

五、交换操作

void swap(map<K,V>& m);    // 把当前容器与m交换。

交换的是树的根结点。

六、比较操作

bool operator == (const map<K,V>& m) const;

bool operator != (const map<K,V>& m) const;

七、查找操作

1)查找键值为key的键值对

在map容器中查找键值为key的键值对,如果成功找到,则返回指向该键值对的迭代器;失败返回end()。

iterator find(const K &key);

const_iterator find(const K &key) const;  // 只读。

2)查找键值>=key的键值对

在map容器中查找第一个键值>=key的键值对,成功返回迭代器;失败返回end()。

iterator lower_bound(const K &key);

const_iterator lower_bound(const K &key) const;  // 只读。

3)查找键>key的键值对

在map容器中查找第一个键值>key的键值对,成功返回迭代器;失败返回end()。

iterator upper_bound(const K &key);

const_iterator upper_bound(const K &key) const;  // 只读。

4)统计键值对的个数

统计map容器中键值为key的键值对的个数。

size_t count(const K &key) const;

八、插入和删除

1)void insert(initializer_list<pair<K,V>> il);  // 用统一初始化列表在容器中插入多个元素。

2)pair<iterator,bool> insert(const pair<K,V> &value);  // 在容器中插入一个元素,返回值pair:first是已插入元素的迭代器,second是插入结果。

3)void insert(iterator first,iterator last);  // 用迭代器插入一个区间的元素。

4)pair<iterator,bool> emplace (...);  // 将创建新键值对所需的数据作为参数直接传入,map容器将直接构造元素。返回值pair:first是已插入元素的迭代器,second是插入结果。

例:mm.emplace(piecewise_construct, forward_as_tuple(8), forward_as_tuple("冰冰", 18));

5)iterator emplace_hint (const_iterator pos,...); // 功能与第4)个函数相同,第一个参数提示插入位置,该参数只有参考意义,如果提示的位置是正确的,对性能有提升,如果提示的位置不正确,性能反而略有下降,但是,插入是否成功与该参数元关。该参数常用end()和begin()。成功返回新插入元素的迭代器;如果元素已经存在,则插入失败,返回现有元素的迭代器。

6)size_t erase(const K & key);  // 从容器中删除指定key的元素,返回已删除元素的个数。

7)iterator erase(iterator pos);  // 用迭代器删除元素,返回下一个有效的迭代器。

8)iterator erase(iterator first,iterator last);  // 用迭代器删除一个区间的元素,返回下一个有效的迭代器。

示例代码:

#include <iostream>
#include <map>
using  namespace std;int main()
{map<string, string> m({ { "08","冠希" }, { "03","于晏" }, { "01","彦祖" }, { "07","德华" }, { "05","学友" } });// 执行插入操作并检查返回值auto result = m.insert(make_pair("08", "富城"));// result的类型是std::pair<std::map<std::string, std::string>::iterator, bool>// result.first是指向插入位置的迭代器(如果插入成功)或已存在相同键的迭代器(如果插入失败)// result.second是一个布尔值,表示插入是否成功if (result.second) {std::cout << "插入成功" << std::endl;}else {std::cout << "插入失败,键已存在" << std::endl;}for (auto& val : m)cout << val.first << "," << val.second << "  ";cout << endl;// 在map容器中查找键值为key的键值对,如果成功找到,则返回指向该键值对的迭代器;失败返回end()。auto it1 = m.find("05");if (it1 != m.end())cout << "查找成功:" << it1->first << "," << it1->second << endl;elsecout << "查找失败。\n";// 在map容器中查找第一个键值 >= key的键值对,成功返回迭代器;失败返回end()。auto it2 = m.lower_bound("05");if (it2 != m.end())cout << "查找成功:" << it2->first << "," << it2->second << endl;elsecout << "查找失败。\n";//	在map容器中查找第一个键值 > key的键值对,成功返回迭代器;失败返回end()。auto it3 = m.upper_bound("05");if (it3 != m.end())cout << "查找成功:" << it3->first << "," << it3->second << endl;elsecout << "查找失败。\n";//	统计map容器中键值为key的键值对的个数。cout << "count(05)=" << m.count("05") << endl;   // 返回1。cout << "count(06)=" << m.count("06") << endl;   // 返回0。
}

运行结果: 

std::map 的 insert 函数在遇到重复键的情况时,会根据其内部实现做出相应处理。通常情况下,它不会覆盖已有的键值对(与 std::unordered_map 不同,std::unordered_map 若插入重复键,会覆盖原来的值),而是会返回一个表示插入结果的对象,这个对象包含了一些信息来表明插入操作是否真正成功插入了新元素。 我们可以接受返回值来确认是否插入成功。

在容器中插入一个元素,返回值pair:first是已插入元素的迭代器,second是插入结果。

按照字符串的字典序比较规则(这也是 std::map 默认用于比较键的规则,因为键是 std::string 类型):

"01" < "03" < "05" < "07" < "08"

所以查找lower和upper时候会找到学友和德华;

unordered_map容器

unordered(无序)

unordered_map容器封装了哈希表,查找、插入和删除元素时,只需要比较几次key的值。

包含头文件: #include<unordered_map>

unordered_map容器的元素是pair键值对。

unordered_map类模板的声明:

template <class K, class V, class _Hasher = hash<K>, class _Keyeq = equal_to<K>,

    class _Alloc = allocator<pair<const K, V>>>

class unordered_map : public _Hash<_Umap_traits<K, V, _Uhash_compare<K, _Hasher, _Keyeq>, _Alloc, false>>

{

      …

}

第一个模板参数Kkey的数据类型(pair.first)。

第二个模板参数Vvalue的数据类型(pair.second)。

第三个模板参数_Hasher:哈希函数,默认值为std::hash<K>

第四个模板参数_Keyeq:比较函数,用于判断两个key是否相等,默认值是std::equal_to<K>

第五个模板参数_Alloc:分配器,缺省用newdelete

创建std::unordered_map类模板的别名:

template<class K,class V>

using umap = std::unordered_map<K, V>;

std::map 和 std::unordered_map 区别:

1. 底层数据结构

  • std::map

    • std::map 的底层数据结构是基于红黑树(Red-Black Tree)实现的。红黑树是一种自平衡二叉搜索树,它在插入和删除节点时会通过一系列的旋转和颜色调整操作来保持树的平衡,使得树的高度始终保持在一个相对较低的水平(最坏情况下为 O(logn),其中n  是树中节点的数量)。
    • 这种数据结构的优点是能够保证元素按照键的大小顺序进行有序存储,并且在查找、插入和删除操作时,平均时间复杂度都为O(logn) 。例如,当你插入一个新的键值对到 std::map 中时,它会根据键的大小在红黑树中找到合适的位置进行插入,并自动调整树的结构以保持平衡和有序。
  • std::unordered_map

    • std::unordered_map 的底层数据结构是基于哈希表(Hash Table)实现的。哈希表通过一个哈希函数将键映射到一个特定的桶(Bucket)中,每个桶可以存储一个或多个键值对。理想情况下,当哈希函数设计得比较好时,查找操作可以在常数时间O(1)  内完成,因为可以通过计算键的哈希值直接定位到对应的桶,然后在桶内进行查找。
    • 然而,哈希表存在哈希冲突(Hash Collision)的问题,即不同的键可能通过哈希函数计算得到相同的哈希值,从而被映射到同一个桶中。为了解决哈希冲突,通常会采用一些冲突解决策略,如链地址法(将冲突的键值对链接成一个链表存放在同一个桶中)或开放地址法(通过一定的规则在哈希表中重新寻找空闲的位置来存放冲突的键值对)。

2、元素顺序

由于其基于红黑树的实现,std::map 中的元素会按照键的大小顺序自动进行排序。unordered_map 中的元素是无序的,因为哈希表本身并不保证元素的顺序。键值对在哈希表中的存储位置主要取决于键的哈希值以及冲突解决策略。所以,当你遍历 unordered_map 时,元素的出现顺序是不确定的,可能与插入顺序不同,也不一定按照键的任何特定顺序排列

例如:

#include <iostream>
#include <unordered_map>int main() {std::unordered_map<int, std::string> myUnorderedMap;myUnorderedMap.insert({ 1, "one" });myUnorderedMap.insert({ 3, "three" });myUnorderedMap.insert({ 2, "two" });// 遍历unordered_map输出所有键值对,顺序不确定for (auto it = myUnorderedMap.begin(); it != myUnorderedMap.end(); ++it) {std::cout << "键:" << it->first << ", 值:" << it->second << std::endl;}return 0;
}

 

这个结果每次输出结果都一样,这其实是有一定概率会出现的情况。虽然理论上 std::unordered_map 的遍历顺序是不确定的,因为它是基于哈希表实现的,元素存储位置取决于键的哈希值以及哈希冲突解决策略等因素。但在实际情况中,如果数据量比较小,而且哈希函数(std::unordered_map 默认的哈希函数或者你自定义的哈希函数,如果有的话)对于你所插入的这些键计算出来的哈希值分布相对比较均匀,没有产生过多的哈希冲突,那么就有可能每次遍历输出的顺序看起来是一样的

不过,当你插入的数据量逐渐增大,或者插入一些特殊的键值使得哈希冲突情况发生变化时,就很可能会出现不同的遍历顺序了。

例如:

#include <iostream>
#include <unordered_map>
#include<random>
#include<utility>
int main() {std::unordered_map<int, int> myUnorderedMap;for (int i = 1; i < 1000000; i++){std::random_device rd;std::mt19937 gen(rd());// 定义分布范围为1到1000000std::uniform_int_distribution<> dis(1, 1000000);// 生成随机数int randomNumber = dis(gen);myUnorderedMap.insert(std::make_pair(i, randomNumber));}// 遍历unordered_map输出所有键值对,顺序不确定for (auto it = myUnorderedMap.begin(); it != myUnorderedMap.end(); ++it) {std::cout << "键:" << it->first << ", 值:" << it->second << std::endl;}return 0;
}

如果生成的数足够多,顺序是不确定的。

3、查找、插入和删除操作的性能特点

  • std::map

    • 查找、插入和删除操作的平均时间复杂度都是 O(logn)。这意味着在数据量较大时,这些操作的执行时间会随着数据量的增加而以对数级别的速度增长。虽然这种增长速度相对较慢,但相比一些常数时间复杂度的操作(如理想情况下的哈希表查找)还是要慢一些。不过,由于 std::map 能够保持元素的有序性,在一些需要基于顺序进行查找(如查找某个键值对之后的所有键值对)或者进行范围查找(如查找键在某个区间内的所有键值对)的场景下,它具有独特的优势。
  • std::unordered_map

    • 在理想情况下,查找操作的时间复杂度可以达到 O(1),即可以在常数时间内完成查找。这是因为通过哈希函数可以直接定位到键值对可能所在的桶,然后在桶内进行查找。然而,实际情况中,由于哈希冲突的存在,当哈希冲突比较严重时,查找操作可能会退化为链表查找(如果采用链地址法解决冲突),此时查找时间复杂度可能会变为O(n) ,其中  是桶内键值对的数量。插入和删除操作的时间复杂度也类似,在理想情况下为 O(1),但在哈希冲突严重时可能会变差。总体来说,当哈希函数设计得比较好,并且哈希冲突不太严重时,std::unordered_map 在查找、插入和删除操作上的性能要优于 std::map

4. 内存占用

  • std::map

    • 由于红黑树需要存储节点之间的指针以及用于保持树平衡的额外信息(如节点的颜色等),相对来说内存占用可能会比 std::unordered_map 要多一些。具体的内存占用情况还会受到键值对类型、树的大小等因素的影响。
  • std::unordered_map

    • std::unordered_map 的内存占用主要取决于哈希表的大小(即桶的数量)以及键值对的数量。一般来说,为了减少哈希冲突,哈希表可能需要设置较大的桶数,这可能会导致一定的内存浪费。但总体而言,在数据量较大且哈希冲突不严重的情况下,std::unordered_map 的内存占用可能相对 std::map 会有一定的优势。

5、总结

std::map 和 std::unordered_map 各有优缺点,在实际应用中,需要根据具体的应用场景和需求来选择合适的容器。如果需要元素按照键的顺序存储并且对查找、插入和删除操作的平均性能要求不是特别高(能够接受O(logn)  的时间复杂度),那么 std::map 是一个不错的选择;如果更看重查找、插入和删除操作的快速执行(希望在理想情况下达到 O(1) 的时间复杂度),并且不需要元素按照特定顺序排列,那么 std::unordered_map 则更为合适。 

相关文章:

简述C++map容器

pair键值对 std::pair在很多关联容器&#xff08;如std::map、std::multimap、std::set、std&#xff1a;multiset等&#xff09;中被广泛应用。以std::map为例&#xff0c;std::map是一个键值对的容器&#xff0c;其中每个元素都是一个std::pair&#xff0c;键用于唯一标识元…...

Vue 学习随笔系列十七 -- 表格样式修改

表格样式修改 文章目录 表格样式修改一、表格背景颜色修改1、方法一2、方法二 二、多级表头颜色修改 一、表格背景颜色修改 1、方法一 表格外套一个 div &#xff0c;修改div的背景色&#xff0c;并将表格背景色设置为透明 参考代码&#xff1a; <template><div cl…...

08 —— Webpack打包图片

【资源模块 | webpack 中文文档 | webpack中文文档 | webpack中文网】https://www.webpackjs.com/guides/asset-modules/?sid_for_share99125_3 Webpack打包图片以8KB为临界值判断 大于8KB的文件&#xff1a;发送一个单独的文件并导出URL地址 小于8KB的文件&#xff1a;导出一…...

01.Django快速入门

一、Django 快速入门 使用最新版本 Django4.2LTS 版本,3 年内不需要更换版本由浅入深讲解&#xff0c;浅显易懂课程大纲全面包含 Django 框架知识点&#xff0c;内容丰富全面细致知识点结合项目实战实现全栈项目应用 Django 官网(文档): https://docs.djangoproject.com/zh-h…...

【大数据学习 | Spark-Core】spark-shell开发

spark的代码分为两种 本地代码在driver端直接解析执行没有后续 集群代码&#xff0c;会在driver端进行解析&#xff0c;然后让多个机器进行集群形式的执行计算 spark-shell --master spark://nn1:7077 --executor-cores 2 --executor-memory 2G sc.textFile("/home/ha…...

Modern Effective C++ Item 14 如果函数不抛出异常请使用noexcept

C11 noexcept关键字用于指定函数不会抛出异常&#xff0c;有助于提高程序的异常安全性&#xff0c;还能够使编译器生成更加高效的代码。 noexcept 是函数接口的一部分 函数是否声明为 noexcept 是接口设计的一部分&#xff0c;客户端代码可能会依赖这一点。如果一个函数被声明…...

cudatoolkit安装(nvcc -V错误版本解决)

CudaToolKit安装&#xff08;nvcc&#xff09; cudatoolkit 是 CUDA 开发工具包&#xff08;CUDA Toolkit&#xff09; 的核心部分&#xff0c;包含了一系列用于开发和运行 CUDA 应用程序的软件组件。nvcc 是 NVIDIA CUDA 编译器驱动&#xff0c;用于将 CUDA C/C 代码编译成可…...

DTO和VO的区别及使用场景详解

随着互联网的发展&#xff0c;前后端分离的开发模式越来越流行。在前后端数据交互过程中&#xff0c;为了保证数据的安全性和效率&#xff0c;通常会采用 DTO 和 VO 来封装数据。本篇博客将详细介绍 DTO 和 VO 的区别以及使用场景。 大家可能会有个疑问&#xff0c;既然DTO是展…...

百度在下一盘大棋

这两天世界互联网大会在乌镇又召开了。 我看到一条新闻&#xff0c;今年世界互联网大会乌镇峰会发布“2024 年度中国互联网企业创新发展十大典型案例”&#xff0c;百度文心智能体平台入选。 这个智能体平台我最近也有所关注&#xff0c;接下来我就来讲讲它。 百度在下一盘大棋…...

第十六届蓝桥杯模拟赛第二期题解—Java

第十六届蓝桥杯模拟赛/校赛第二期个人题解&#xff0c;有错误的地方欢迎各位大佬指正 问题一(填空题) 【问题描述】 如果一个数 p 是个质数&#xff0c;同时又是整数 a 的约数&#xff0c;则 p 称为 a 的一个质因数。 请问&#xff0c; 2024 的最大的质因数是多少&#xff1f; …...

驱动开发笔记:关于3588GPIO

1.概要 2.内容 1.3588GPIO 关于RK3588的GPIO&#xff08;General-Purpose Input/Output&#xff0c;通用输入输出引脚&#xff09;&#xff0c;以下是一些关键信息和操作指南&#xff1a; 一、GPIO基本概念 定义&#xff1a;GPIO是嵌入式系统中常见的通信接口&#xff0c;…...

【RK3588 Linux 5.x 内核编程】-内核线程与Mutex

内核线程与Mutex 文章目录 内核线程与Mutex1、Mutex介绍1.1 竞争条件1.2 Mutex特性2、Linux内核中的Mutex2.1 初始化Mutex2.1.1 静态方式初始化2.1.2 动态方式初始化2.2 互斥锁获取2.3 互斥锁释放3、Mutex使用示例4、驱动验证在前面的文章中,介绍了如何Linux内核中的线程,但是…...

【0342】分配并初始化 Proc Signal 共享内存 (1)

1. Proc Signal (procsignal)共享内存 Postgres内核在启动postmaster守护进程时候, 会通过函数 ProcSignalShmemInit() 去为 Proc Signal 分配并初始化指定大小的共享内存空间。整个调用链路如下。 (gdb) bt #0 ProcSignalShmemInit () at procsignal.c:118 #1 0x000000000…...

管家婆财贸ERP BR035.回款利润明细表

最低适用版本: 财贸系列 23.5 插件简要功能说明: 报表统计销售单/销售退货单/销售发票回款情况更多细节描述见下方详细文档插件操作视频: 进销存类定制插件--回款利润明细表 插件详细功能文档: 1. 应用中心增加报表【回款利润明细表】 a. b. 查询条件: ⅰ. 日期区间:…...

数据库MYSQL——表的设计

文章目录 前言三大范式&#xff1a;几种实体间的关系&#xff1a;一对一关系&#xff1a;一对多关系&#xff1a;多对多关系&#xff1a; 前言 之前的博客中我们讲解的是关于数据库的增删改查与约束的基本操作&#xff0c; 是在已经创建数据库&#xff0c;表之上的操作。 在实…...

netstat -tuln | grep 27017(显示所有监听状态的 TCP 和 UDP 端口,并且以数字形式显示地址和端口号)

文章目录 1. 确定占用端口的进程使用 lsof 命令使用 fuser 命令 2. 结束占用端口的进程3. 修改 MongoDB 配置文件4. 检查 MongoDB 日志文件5. 重新启动 MongoDB 服务6. 检查 MongoDB 服务状态总结 [rootlocalhost etc]# netstat -tuln | grep 27017 tcp 0 0 127.0.…...

非线性控制器设计原理

非线性控制器设计原理 非线性控制器设计旨在解决非线性系统的控制问题&#xff0c;克服传统线性控制器在处理非线性现象&#xff08;如饱和、死区、耦合、时变性等&#xff09;时的不足。其核心在于利用非线性数学工具和设计方法&#xff0c;使控制系统在非线性条件下具备良好…...

MySQL数据库6——SQL优化

一.SQL优化 1.插入优化 优化1&#xff1a;批量插入 insert into 表名 values(记录1),(记录2),……;优化2&#xff1a;手动提交事务 start transaction; insert into 表名 values(记录1),(记录2); insert into 表名 values(记录1),(记录2); …… commit;优化3&#xff1a;主键顺…...

IDEA配置本地maven

因为idea和maven是没有直接关系的。所以使用idea创建maven工程之前需要将本地的maven配置到idea环境中&#xff0c;这样才可以在idea中创建maven工程。配置方法如下&#xff1a; 1.1 配置本地maven 第一步&#xff1a;关闭当前工程&#xff0c;回到idea主界面找到customize--…...

学习日记_20241123_聚类方法(高斯混合模型)续

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...