c++的STL(6)-- map和multimap

map和multimap概述

  • map和multimap中存储的是使用pair对象的键值对。 
  • map和multimap底层也是使用红黑树的数据结构进行实现的。所以,map和multimap内部存储的键值对也是有序的。并且内部数据也是使用链表的形式进行关联。所以其的迭代器和指针,也只能进行++,--(前置和后置),==,!=
  • 而且和set一样map的键不能重复。(值可以) multimap可以重复。
  • map容器的键是不支持修改的,map<const 键类型,值类型>
  • map支持我们使用[]和at()函数,方便我们通过键来操作其对应的值。

表 C++ map容器常用成员方法
成员方法功能
begin()返回指向容器中第一个(注意,是已排好序的第一个)键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
end()返回指向容器最后一个元素(注意,是已排好序的最后一个)所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
rbegin()返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
rend()返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
cbegin()和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
cend()和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
crbegin()和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
crend()和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
find(key)在 map 容器中查找键为 key 的键值对,如果成功找到,则返回指向该键值对的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
lower_bound(key)返回一个指向当前 map 容器中第一个大于或等于 key 的键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
upper_bound(key)返回一个指向当前 map 容器中第一个大于 key 的键值对的迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
equal_range(key)该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的键为 key 的键值对(map 容器键值对唯一,因此该范围最多包含一个键值对)。
empty() 若容器为空,则返回 true;否则 false。
size()返回当前 map 容器中存有键值对的个数。
max_size()返回 map 容器所能容纳键值对的最大个数,不同的操作系统,其返回值亦不相同。
operator[]map容器重载了 [] 运算符,只要知道 map 容器中某个键值对的键的值,就可以向获取数组中元素那样,通过键直接获取对应的值。
at(key)找到 map 容器中 key 键对应的值,如果找不到,该函数会引发 out_of_range 异常。
insert()向 map 容器中插入键值对。
erase()删除 map 容器指定位置、指定键(key)值或者指定区域内的键值对。后续章节还会对该方法做重点讲解。
swap()交换 2 个 map 容器中存储的键值对,这意味着,操作的 2 个键值对的类型必须相同。
clear()清空 map 容器中所有的键值对,即使 map 容器的 size() 为 0。
emplace()在当前 map 容器中的指定位置处构造新键值对。其效果和插入键值对一样,但效率更高。
emplace_hint()在本质上和 emplace() 在 map 容器中构造新键值对的方式是一样的,不同之处在于,使用者必须为该方法提供一个指示键值对生成位置的迭代器,并作为该方法的第一个参数。
count(key)在当前 map 容器中,查找键为 key 的键值对的个数并返回。注意,由于 map 容器中各键值对的键的值是唯一的,因此该函数的返回值最大为 1。

map和multimap使用必须导入头文件#include<map> 

1. map的默认构造 

代码 

int main(void) {
	/*
		map<string, int> m1;
		map<int, int>m2;
		map<Student,int>m3;
		map<Student,Student*>m4;
		map<int,int*>m5;
	*/
	system("pause");
	return 0;
}

2. map的有参构造 

代码 

	/*
		map<string, int> m1({ {"张三",18},{"李四",20} });
		map<string, int> m1{ {"张三",18},{"李四",20} };

		pair<string, int> p1("张三",20);
		pair<string, int> p2("李四",30);
		map<string, int> m2({p1,p2});
		map<string, int> m2{p1,p2};

		map<string, int> m3(m1.begin(), m1.end());
		map<string, int> m3{ m1.begin(), m1.end() };

        map<string,int> m3(m1);  // 调用拷贝构造函数
        
	    // 借助make_pair()函数
	    map<string, int> m1({ make_pair("张三", 18) });
	    map<string, int> m1{ make_pair("张三", 18) };
	*/

3.map容器元素的个数 

代码:  使用size()函数 

int main(void) {
	map<string, int>m1{ {"数学",108},{"语文",80},{"英语",100} };

	cout << "m1的键值对个数:" << m1.size() << endl;  // 3

	system("pause");
	return 0;
}

代码: 使用count()函数 

int main(void) {
	map<string, int>m1{ {"数学",108},{"语文",80},{"英语",100} };

	map<string,int>::size_type t1 = m1.count("数学");
	cout << t1 << endl;

	system("pause");
	return 0;
}
相关知识点 
  •  count(elem)函数,以map中存储的键值对的键为参数,返回键值为elem的键值对的个数。
  • 因为map中的键是唯一的,所以count()函数返回的值为0或者1,multimap返回可能大于1
  • size_type在vector中已经说到过了。

4.map的元素访问(有变动) 

代码:  使用[]和at()

int main(void) {
	string s1(20, '-');
	map<string, int>m1{ {"数学",108},{"语文",80},{"英语",100} };

	// 使用[]访问
	cout << "键: 数学, 值: " << m1["数学"] << endl;
	cout << s1 << endl;

	// 使用[]修改
	m1["数学"] = 110;
	// 使用[]添加
	m1["政治"] = 90;

	for (map<string, int>::iterator it = m1.begin(); it != m1.end(); it++) {
		cout << "键:" << (*it).first << " 值: " << (*it).second << endl;
	}
	cout << s1 << endl;

	// 使用at()访问
	cout << "键: 数学, 值: " << m1.at("数学") << endl;
	cout << s1 << endl;

    // 使用at()修改
	m1.at("语文") = 110;

	for (map<string, int>::iterator it = m1.begin(); it != m1.end(); it++) {
		cout << "键:" << (*it).first << " 值: " << (*it).second << endl;
	}
	cout << s1 << endl;

	system("pause");
	return 0;
}
相关知识点 
  • map和set不同,map是可以使用[]下标运算符来进行访问数据的,不止如此,我们也可以通过[]将对应键的值进行修改
  • map还可以通过[]添加元素,当[]中的使用的键值不存在的时候,那么[]运算符就会将对应的键值对添加到map中去。 
  • 同样,map也可以使用at()函数,访问键对应的值。也可以将键对应的值进行修改
  • 但是,通过at()不能给map添加元素,如果at()中的键值不存在,at()函数会抛出异常

5.map的迭代器 

表  map 容器迭代器相关成员方法
成员方法功能
begin()返回指向容器中第一个(注意,是已排好序的第一个)键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
end()返回指向容器最后一个元素(注意,是已排好序的最后一个)所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
rbegin()返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
rend() 返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
cbegin()和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
cend() 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
crbegin() 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
crend() 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。

map的迭代器也值能进行++,--(前置和后置)的运算操作,==,!=的比较操作,以及不能使用迭代器修改键的值。

其它的操作和前面的容器是想用的。

6. map在指定位置插入元素

代码:  使用insert()函数 

	/*
	map<string, int> m1;

	pair<string, int> p1("张三", 18);
	m1.insert(p1);
	m1.insert(pair<string, int>("李四", 20));
	m1.insert(m1.begin(), p1);
	m1.insert({ p1,pair<string,int>("王五",30) });

	// 使用make_pair构建并返回一个pair对象,然后添加
	m1.insert(make_pair("张三", 25));
	// 使用内置类型value_type对象(value_type表示存储在容器中的元素类型,此处为pair类型)
	m1.insert(map<string, int>::value_type("张三", 25));
	*/
相关知识点 

我们前面说过map找那个存放的是键值对,也就是pair的队组形式,所以我们使用insert插入数据的时候,应该插入pair对象。 

使用make_pair()函数和value_type对象插入
  • make_pair(value1,value2);  // 此函数用于构建一个pair对象,然后返回,将返回的pair对象插入map中。
  • value_type 是容器内部的一个类,其表示容器中存储数据的类型,map中存储的类型就是pair类型,所以此时value_type就表示pair,创建的对象也是pair对象。 

insert()返回值 

  1. 当我们直接插入pair对象,insert函数返回一个pair<iterator,bool>。迭代器指插入元素的位置(插入失败,指向键值与插入元素相同的元素位置),bool表示插入是否成功 (如果map中存放的键值和插入数据的键值有相同则会插入失败)。
  2.  当我们在指定位置插入pair对象时,insert(iterator,pair);  // 其返回一个迭代器,指向插入元素的位置(插入失败,指向键值与插入元素相同的元素位置)
  3. 当使用初始化列表进行插入的时候,insert()返回void。(因为初始化列表一次可以插入多个pair对象)

 

代码:   使用emplace()和emplace_hint()函数

map<string, int> m1;

// emplace()函数
m1.emplace("张三",20);
m1.emplace("李四", 21);

// emplace_hint()函数
m1.emplace_hint(m1.begin(), "张三", 20);
相关知识点 
  1. emplace()我们之前用到过,是c++11为了增加insert效率问题,提出的函数,这里同样使用emplace()函数给map对象添加键值对,不需要创建pair对象,我们直接在emplace()函数的参数中写上要添加的键值对就行,其内部会自己在相应位置创建一个pair对象。
两函数的区别 
  • emplace()和emplace_hint()的区别是,emplace_hint()函数的第一个参数传入一个迭代器,用来指向插入元素的位置,后面的参数形式和emplace()一样。 (也就是输emplace_hint()用于在指定位置插入数据)
在指定位置插入时应该注意 
  •  map在指定位置插入数据和set是一样的,因为其都是有序的,所以即使我们指定了插入的位置,我们插入的数据也不一定会在对应位置上,因为插入的时候底层会根据你插入的键值与原来数据进行比较,放到相应的位置上。 所以,即使我们指定了插入位置,数据也不一定会放到哪个位置。

 

 7. map删除元素

代码:  erase()和clear()函数 

map<string, int> m1{ {"张三",25},{"李四",26} };

// 擦除对应的数据
m1.erase("张三");
m1.erase(m1.begin());
m1.erase(m1.begin(), m1.end());

// 请空map中的元素
m1.clear();
相关知识点 
  • erase(key);  // 删除键值为key的键值对
  • erase(iter);  // 删除迭代器iter指向位置的键值对
  • erase(beg,end);  // 删除迭代器beg和迭代器end范围内的键值对
  • clear();  // 删除map中所有的键值对 
erase()函数的返回值 
  • erase(key);  // 返回的是size_t(或者size_type)类型,用于表示删除的键值个数。(因为map中的键不能相同,所以使用这重载返回的值只能为1或者0,但是multimap就可以大于1了) 

     map<string,int>::size_type t = m1.erase("张三");

  • erase(iter);和erase(beg,end);  // 返回的是删除键值对下一个键值对的迭代器。

    map<string,int>::iterator it1 = m1.erase(m1.begin());
    map<string,int>::iterator it2 = m1.erase(m1.begin(), m1.end());

erase()函数和循环结合删除元素时注意事项 

注意:  在erase和循环结合使用的时候,应该注意删除时迭代器的指向。(在vector中详述)

 
8. map查找元素  

代码: 使用find()函数

map<string, int> m1{ {"张三",25},{"李四",26} };

map<string,int>::iterator it1 = m1.find("张三");

if (it1 != m1.end()) {
	cout << (*it1).first << ":" << (*it1).second << endl;
}
else {
	cout << "没有找到!!!" << endl;
}
相关知识点 
  • find(key);   // 查找对应键值的键值对,返回一个迭代器,指向与key相同键值的元素。 
如何判断find()是否查找成功 
  • find()如果没有找到对应元素,那么就会返回一个和end()函数返回值一样的迭代器,所以我们判断是否查找成功,就可以通过find()返回的迭代器是否等于end()返回的迭代器

 

代码:使用[]和at()访问 

在前面已经说过了 

 

 代码: 使用lower_bound(),upper_bound()和equal_range()函数

map<int, string> m1{ {25,"张三"},{26,"李四"} };

map<int, string>::iterator it1 = m1.lower_bound(25);
map<int, string>::iterator it2 = m1.upper_bound(25);
pair<map<int, string>::iterator,map<int, string>::iterator> p1 = m1.equal_range(25);
相关知识点 
  • lower_bound(key);  // 此函数返回指向map中键值对的键值>=key的第一个元素的迭代器(迭代器指向的是pair类型)
  • upper_bound(key);  // 此函数返回指向map中键值对的键值>key的第一个元素的迭代器
  • equal_range(key);  // 此函数返回一个pair对象,内部包含两个迭代器,第一个迭代器指向键值与key相同的第一个键值对的位置,第二个迭代器指向键值与key相同的最后一个键值对的下一个位置。(因为map中的键值不能相同,所以对于map两个迭代器的范围最大为1,但是对于multimap就可以大于1了)
如果没有我们要找的键值会怎么样 
  • 如果key不存在,那么两个迭代器就都指向按照规则key的下一个元素,(如果从小到大排列就指向第一个key的元素)。 当然如果按照规则,set排在最后,则两个迭代器都指向最后一个元素的下一位。(比如:  从小到大排时,set比map中的元素都要大)
  • 举个例子,lower_bound(key); 要找到是>=key的键值对(并且排序是从小到大排),如果键值为key的键值对不存在,那么返回的两个迭代器,就会指向第一个键值>key的键值对。

 

9. map的排序规则 

  • map和set是类似的,其内部都是有序的,同样我们也都可以指定数据的排序规则(使用函数对象)
  • 在默认情况下map是使用内置的less函数对象,进行从小到大排序的。 
map<int, string,greater<int>> m1{ {25,"张三"},{26,"李四"} };
  • 上面我们使用另外一个内置的函数对象greater,其是让map从大到小排列。
  • 注意:   函数对象我们只需要指定一个类型就行,用这个类型的数据作为排序的数据。 

 

10. map的value_comp()函数 

map<int, string, greater<int>>::value_compare v1 = m1.value_comp();

map<int, string, greater<int>>::value_type t1 = make_pair(25,"张三");
map<int, string, greater<int>>::value_type t2 = make_pair(26,"李四");

if (v1(t1, t2)) {
	cout << "t1在t2之前" << endl;
}
else {
	cout << "t2在t1之后" << endl;
}

相关知识点 

  • value_comp();  // 返回一个map<>::value_compare的函数对象。
  • 此函数对象重载的()运算符,支持两个类型为value_type的参数。(就是容器内存储数据的类型,map中为pair) 
  • 我们可以使用value_compare的函数对象,传入两个对应类型的参数,其会返回第一个个参数的键是否在第二个参数的键的前面,如果是:返回true,如果不是:返回false

注意:  上面判断第一个参数的键是否在第二个参数的键的前面,是根据我们指定的容器的排序规则进行判断的。

比如:  map指定从小到大排,键25就在键26的前面。

注意:  两个参数只要满足类型规则就行,不需要在容器当中,可以理解为用来判断value_type类型的数据,在容器指定的规则下谁前谁后。

 

11. map中的key_comp()函数 

map<int, string,greater<int>> m1{ {25,"张三"},{26,"李四"} };

greater<int> g1 = m1.key_comp();

if (g1(1, 2)) {
	cout << "1在2之前" << endl;
}
else {
	cout << "1在2之后" << endl;
}

 相关知识点

  •  key_comp();  // 无参数,返回一个函数对象或者函数指针,也就是我们指定的容器排序规则。(map是第三个类型参数指定)

如上:  代码中我们使用的map容器使用greater的内置函数对象进行排序,所以此函数返回的就是一个greater的函数对象。

  • 我们可以使用返回的函数对象重载的()运算符,传入对应类型的两个参数,根据对应的规则判断传入参数谁前谁后。(按照规则,第一个参数在前返回true,第一个参数再回返回false)

 

 12. map的其它函数

  • swap(m1);  //使调用此函数的map容器和m1的元素进行互换
  • empty();  // 判断map容器是否为空
  • max_size();  // 和vector类似  

 

13. map和multimap的不同之处 

multimap和map的函数大多数在使用的时候都是一样的,我们就不再说明了。

但是由于multimap可以存放不同的元素所以和map会有点区别。 

区别:

  • multimap在调用erase(key),方法时期返回值可以大于1。
  • 同理count(key)这个函数的返回值也可以大于1。
  • lower_bound(key)、upper_bound(key)、equal_range(key)其对应查找的数据范围也不再是一个,所以这些函数更加常用于multimap。

注意事项 

  • 由于map内部是有序的,所以我们不能随便修改其内部的值,因为如果修改了某一位置的值,很可能会导致其不再是有序排列的了。所以使用迭代器(即使迭代器不是const修饰的)或者其它方式都不能对map中的元素进行修改。如果要修改,那必须将这个元素删除,然后再添加一个新元素。
  • size_type和value_type和vector的用法一样。(或者其他的内嵌类型)
  • multimap是类似的。

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

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

相关文章

淘宝商品详情用于选品上架,数据分析,代购商城建站,ERP系统商品数据选品,价格监控业务场景

大数据时代&#xff0c; 数据收集不仅是科学研究的基石&#xff0c; 更是企业决策的关键。 然而&#xff0c;如何高效地收集数据 成了摆在我们面前的一项重要任务。 本文将为你揭示&#xff0c; 一系列实时数据采集方法&#xff0c; 助你在信息洪流中&#xff0c; 找到…

分享一个宝藏课程:近屿AIGC工程师和产品经理训练营

说起AIGC&#xff0c;大家都会自然地想到近两年火的一塌糊涂的ChatGPT,而开发出它的OpenAI&#xff0c;去年年底的年化收入已突破16亿美元&#xff0c;部分OpenAI的管理层认为&#xff0c;按目前进度&#xff0c;到2024年底&#xff0c;OpenAI的年化收入至少能达到50亿美元。而…

hyper-v安装 windows10虚拟机后,登录一直是锁屏界面,无法开启增强会话

按键盘等&#xff0c;一直在锁屏界面&#xff0c;进不去&#xff0c;需要点击 上述图片按钮&#xff0c;切到 “基本会话”&#xff0c; 这样可以登录了&#xff1b; 切换到 ‘基本会话’ &#xff0c;登陆后&#xff0c; 打开 设置--登录选项--要求 Microsoft 账户使用Windo…

计算机网络面试问题(一)

1.在浏览器中输⼊URL并按下回⻋之后会发⽣什么 2.TCP三次握⼿的过程,为什么三次握手 TCP&#xff08;传输控制协议&#xff09;的三次握⼿是建⽴⽹络连接的过程&#xff0c;确保通信双⽅能够正确地进⾏数据传输。 第⼀次握⼿&#xff08;SYN&#xff09;&#xff1a; 客户端&am…

【笔记】通过码云Gitee获取OpenHarmony源码

Note&#xff1a;下面包含操作过程和问题解决&#xff08;首次安装Ubuntu&#xff0c;环境未完善&#xff09;&#xff0c;没有遇到问题可以直接跳过问题part了&#xff0c;小白也能完成配置下载。 前置准备&#xff08;Git环境账号&#xff09; &#xff08;一&#xff09;安…

Effective-C++阅读解析条款(条款二:尽量以const,enum,inline替换#define)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 书中说这个条款或许改为“宁可以编译器替换预处理器”比较好&#xff0c;这句话在我看来原因是这样的&#xff1a; 如果我们有这样一个宏(假设写这个宏的人比较粗心)&#xff1a;#define Add(x, y) x y 我们本意是想得到…

“创新强基·应用强链”2024第104届上海电子展会

2024第104届上海电子展会 2024 Shanghai electron Expo 时间:2024年11月18--20日 地点:上海新国际博览中心 主题:创新强基应用强链 上海与长三角各地产业协同发展&#xff0c;到2025年&#xff0c;初步建成具有全球影响力和竞争力的世界级电子信息产业集群。产业链稳定性和韧…

黄金票据制作

1、黄金票据 黄金票据在内网渗透中主要用于权限维持&#xff0c;即留下后门。使用黄金票据前提是你已经控制了整个域的域控制器。其核心原理与服务器中的krbtgt用户相关。从以下可以了解krbtgt原理&#xff1a; 前言 | windows protocolhttps://daiker.gitbook.io/windows-pro…

DNDC模型对所有处理的土壤温度和湿度模拟效果良好,但有时土壤湿度模拟存在偏差

使用 DNDC 模型评估加拿大多样化作物轮作系统对产量和 N2O 排放的影响 原名&#xff1a;Assessing the impacts of diversified crop rotation systems on yields and nitrous oxide emissions in Canada using the DNDC model 译名&#xff1a;使用 DNDC 模型评估加拿大多样…

使用vite创建一个react18项目

一、vite是什么&#xff1f; vite 是一种新型前端构建工具&#xff0c;能够显著提升前端开发体验。它主要由两部分组成&#xff1a; 一个开发服务器&#xff0c;它基于原生 ES 模块提供了丰富的内建功能&#xff0c;如速度快到惊人的模块热更新&#xff08;HMR&#xff09;。 …

站群CMS系统

站群CMS系统是一种用于批量建立和管理网站的内容管理系统&#xff0c;它能够帮助用户快速创建大量的网站&#xff0c;并实现对这些网站的集中管理。以下是三个在使用广泛的站群CMS系统&#xff0c;它们各具特色&#xff0c;可以满足不同用户的需求。 1. Z-BlogPHP Z-BlogPHP是…

PSA制氧设备装置的使用注意事项解析

PSA制氧设备&#xff0c;即变压吸附制氧设备&#xff0c;是一种利用物理吸附原理&#xff0c;通过特定的吸附剂&#xff0c;在压力变化的情况下&#xff0c;从空气中分离出氧气的设备。由于其高效、节能、环保等特点&#xff0c;PSA制氧设备在工业、能源等领域得到了广泛应用。…

QCustomPlot一、QCustomPlot基础及画图显示

1、QCustomPlot下载 QCustomPlot源码demo 根据需要选择需要的文件&#xff1a; 完整版。QCustomPlot.tar.gz 源代码例子帮助文档&#xff1b; 共享库。QCustomPlot-sharedlib.tar.gz 库编译和使用&#xff1b; 源代码。QCustomPlot-source.tar.gz 源代码 里面包含了很多QCusto…

JavaEE 初阶篇-深入了解单例模式(经典单例模式:饿汉模式、懒汉模式)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 单例模式的概述 2.0 单例模式 - 饿汉式单例 2.1 关于饿汉式单例的线程安全问题 3.0 单例模式 - 懒汉式单例 3.1 关于懒汉式单例的线程安全问题 3.1.1 加锁 synchr…

设计模式——行为型——责任链模式Chain Of Responsibility

请求类 public class ApproverRequest {private int type;//请求批准的类型private float price;//请求的金额private int id;//请求的编号 } 审批人抽象类 public abstract class ApproverPerson {protected ApproverPerson next;protected String name;//审批过程public a…

基于SSM+Jsp+Mysql的班级同学录网站

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

深入解析实时数仓Doris:Rollup上卷表与查询

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 目录 一、基本概念二、Aggregate 和 Unique 模型中的 ROLLUP三、Duplicate 模型中的 ROLLUP四、ROLLUP 调整前缀索引五、ROLLUP使…

【Mars3d绘制完成后设置离地面的实体高度】graphicLayer.startDraw绘制带高度的实体

实现效果&#xff1a; 相关需求场景&#xff1a; 绘制之后可以在success中通过graphic可以拿到所点击的点的位置&#xff0c;然后重新生成一个graphic添加到地图上&#xff0c;重新生成的面在初始化的时候可以指定想要的高度 相关实现代码&#xff1a; // 开始绘制多边形 exp…

如何对抓取的文本进行分词、词频统计、词云可视化和情感分析

目录 一、引言 二、文本分词 三、词频统计 四、词云可视化 五、情感分析 六、总结 一、引言 在大数据时代&#xff0c;文本数据的处理和分析显得尤为重要。对于爬虫抓取的大量文本数据&#xff0c;如何进行高效、准确的处理和分析&#xff0c;是每一个数据分析师和开发…

QML 用文件的方式自定义组件

自定义组件 序言方法首先新建一个QML文件QML文件名称创建完后编写自己的组件 效果注意 序言 说到QML&#xff0c;就肯定离不了自定义一说&#xff0c;毕竟你总不至于用一个qml文件写完全部吧&#xff1f;我来写点基础的东西丰富下QML资料贫乏 方法 首先新建一个QML文件 QML文…