C++容器(四):map类型
map 类型
map
是键-值对的集合。map
类型通常可以理解为关联数组:可以使用键作为下标来获取一个值,正如内置数组类型一样。而关联的本质在于元素的值与某个特定的键相关联,而非通过元素在数组内的位置来获取。
要使用map
对象,必须包含map
头文件:
#include <map>
在定义map
对象时,必须指明键和值的类型:
map<string, int> wordCount; // empty map from string to int
1 map
对象的构造函数
操作 | 含义 |
---|---|
map<k, v> m |
创建一个名为m 的map 对象,其键和值的类型分别为k 和v |
map<k, v> m(m2) |
创建m2 的副本m ,m 与m2 必须具有相同的键类型和值类型 |
map<k, v> m(b, e) |
创建map 类型的对象m ,存储迭代器b 和e 标记范围内的所有元素副本。元素的类型必须能够转换为pair<const k, v> |
对于键类型,唯一的约束就是必须支持
<
操作,至于是否支持其他关系或相等运算,则不做要求。
2 map
定义的类型
包括:键类型,值类型以及键-值(pair
)类型。
类型 | 含义 |
---|---|
map<k, v>::key_type |
在map 容器中,用作索引的键的类型 |
map<k, v>::mapped_type |
在map 类型中,键所关联的值的类型 |
map<k, v>::value_type |
一个pair 类型,它的first 元素具有const map<k, v>::key_type 类型,而second 则为map<k, v>::mapped_type 类型 |
map
迭代器进行解引用将产生pair
类型的对象
对迭代器进行解引用时,将获得一个引用,指向容器的一个value_type
类型值。
map<string, int>::iterator map_it = wordCount.begin();
// *map_it is a reference to a pair<const string, int> object
cout << map_it->first << " " << map_it->second << endl; // print the key and value of the element
map_it->first = "new key"; // error: key is const type
++ map_it->second; // ok: we can change value through the iterator
3 给map
添加元素
给map
中添加键-值元素对时,有两种方式:一种是先用下标操作符获取元素,然后给获取的元素赋值,一种是使用insert
成员函数实现。
3.1 使用下标访问map
对象
如编写下段程序时:
map<string, int> wordCount; // empty map
// insert default initialized element with key "Anna"; then assign 1 to its value
wordCount["Anna"] = 1;
将发生以下事情:
- 在wordCount中查找键为
Anna
的元素,没有找到;- 将一个新的键-值对插入到
wordCount
中。它的键是const string
类型的对象,保存Anna
。而它的值则采用值初始化,这就意味着在本例中值为0;- 将这个新的键-值对插入到
wordCount
中;- 读取插入的新元素,并将它的值赋为1。
- 下标操作符返回值的使用
通常来说,下标操作符返回左值。它返回的左值是特定键所关联的值。
cout << wordCount["Anna"] <<endl; // fetch element indexed by Anna; ptint 1
++ wordCount["Anna"]; // fetch the element and add one to it
cout << wordCount["Anna"] << endl; // fetch element and print it; print 2
有别于
vector
或string
类型,map
下标操作符返回的类型与对map
迭代器进行解引用获得的类型不相同。
- 下标行为的编程意义
对于map
容器,如果下标表示的键在容器中不存在,则添加新元素,这一特性可使程序惊人的简练:
// count the number of times each word occurs in the input
map<string, int> wordCount; // empty map from string to int
string word;
while ( cin >> word )
++ wordCount[word];
这段程序创建一个map
对象,用来记录每个单词出现的次数,while
循环每次从标准输入读取一个单词,如果这是一个新的单词,则在wordCount
中添加以该单词为索引的新元素,如果读入单词已经在map
对象中,则将它所对应的值加1。
3.2 insert
成员函数
map
容器的insert
成员与顺序容器的类似,但有一点要注意:必须考虑键的作用。
操作 | 含义 |
---|---|
m.insert(e) |
e 是一个用在m 上的value_type 类型的值。如果键(e.first )不在m 中,则插入一个值为e.second 的新元素;如果键在m 中已经存在,则保持m 不变。该函数返回一个pair 类型对象,包含指向键为e.first 的元素的map 迭代器,以及一个bool 的对象,表示是否插入了该元素 |
m.insert(begin, end) |
begin 和end 是标记元素范围的迭代器,其中的元素必须为m.value_type 类型的键-值对。对于该范围内的所有元素,如果其键在m 中不存在,则将该键及其关联的值插入m 。返回void 类型 |
m.insert(iter, e) |
e 是一个用在m 上的value_type 类型的值。如果键(e.first )不在m 中,则创建新元素,并以迭代器iter 为起点搜索新元素存储的位置。返回一个迭代器,指向m 中具有给定键的元素 |
- 以
insert
代替下标运算
使用下标给map
容器添加新元素时,元素的值部分将采用值初始化。通常,我们会立即为其赋值,其实就是对同一个对象进行初始化并赋值。而insert
其语法更加紧凑:
// if Anna not already in wordCount, inserts new element with value 1
wordCount.insert( map<string, int>::value_type("Anna", 1) );
这个insert
函数版本的实参:
map<string, int>::value_type("Anna", 1)
是一个新创建的pair
对象,将直接插入到map
容器中。但是传递给insert
的实参相当笨拙,有两种方法可以简化:
// first
wordCount.insert( make_pair("Anna", 1) );
// second
typedef map<string, int>::value_type valueType;
wordCount.insert( valueType("Anna", 1) );
前面我们已经学会了,使用下标操作符统计输入的单词,insert
成员函数同样可以实现:
// count number of times each word occurs in the input
map<string, int> wordCount; // empty map from string to int
string word;
while ( cin >> word )
{
// insert element with key equal to word and value 1
// if word already in wordCount, insert does nothing
pair<map<string, int>::iterator, bool> ret =
wordCount.insert(make_pair(word, 1));
if ( !ret->second ) // word already in wordCount
++ ret.first->second; // increment counter
}
本处使用了带有一个键-值pair
形参的insert
版本将返回:包含一个迭代器和一个bool
值的pair
对象,其中迭代器指向map
中具有相应键的元素,而bool
值则表示是否插入了该元素。如果该键已在容器中,则其关联的值保持不变,返回的bool
值为false
;如果该键不在容器中,则插入新元素,且bool
值为true
。对于每个单词,都尝试insert
它,并将它的值赋为1。if
语句检测insert
函数返回值,如果值为false
则表示没有做插入操作;按照word
索引的元素已在wordCount
中存在,此时将该元素所关联的值加1。
4 查找并读取map
元素
下标操作符给出了读取一个值的最简单方法:
map<string, int> wordCount; // empty map from string to int
int occurs = wordCount["Anna"];
但是,该方法存在一个副作用:如果该键不存在map
容器中,则下标操作会插入一个具有该键的新的元素。大多数情况下,我们其实只是想知道某元素是否存在,当该元素不存在时,我们并不打算进行插入运算。为此,map
容器提供的两个操作可以解决这一问题。
操作 | 含义 |
---|---|
m.count(k) |
返回m 中k 的出现次数 |
m.find(k) |
如果m 容器中存在按k 索引的元素,则返回指向该元素的迭代器。如果不存在,则返回指向超出末端迭代器 |
// count()
int occurs(0);
if ( wordCount.count("Anna") )
occurs = wordCount["Anna"];
// find()
int occurs(0);
map<string, int>::iterator iter = wordCount.find("Anna");
if ( iter != wordCount.end() )
occurs = iter->second;
5 从map
对象中删除元素
操作 | 含义 |
---|---|
m.erase(k) |
删除m 中键为k 的元素。返回size_type 类型的值,表示删除的元素的个数 |
m.erase(p) |
从m 中删除迭代器p 所指向的元素。p 必须指向m 中确实存在的元素,而且不能等于m.end() 。返回void 类型 |
m.erase(b, e) |
从m 中删除一段范围内的元素,该范围由迭代器对b 和e 标记。b 和e 必须标记m 中的一段有效范围:即b 和e 都要指向m 中的元素或最后一个元素的下一个位置。并且,b 和e 要么相等(此时删除范围为空),要么b 所指向的元素必须出现在e 所指向的元素之前。返回void 类型 |
// erase of a key returns number of elements removed
if ( wordCount.erase( removalWord ) )
cout << "ok: " << removalWord << " removed!" << endl;
else
cout << "oops: " << removalWord << " not found!" << endl;
6 对map
对象的迭代遍历
// get iterator positioned on the first element
map<string, int>::const_iterator iter = wordCount.begin();
// for each element in the map
while ( iter != wordCount.end() )
{
// print the element key, value pairs
cout << iter->first << " occurs " << iter->second << " times." << endl;
++ iter; // increment iterator to denote the next element
}
参考文献:
- 《C++ Primer中文版(第四版)》,Stanley B.Lippman et al. 著, 人民邮电出版社,2013。
C++容器(四):map类型的更多相关文章
- 哈哈,原来IOC容器的bean是存在DefaultSingletonBeanRegistry的一个Map类型的属性当中。
经过查看源代码发现IOC容器中的bean实例(不知道是不是所有的bean)是存储在一个DefaultSingletonBeanRegistry类实例的一个Map类型的属性当中. 下面是DefaultS ...
- (四)CXF之处理Map类型的数据
一.需求描述 正常来讲webService可以处理Java 数据类型.JavaBean.List等,但是却不能处理Map数据类型.本章讲解如何使用适配器来使得web服务可以处理Map数据类型. 流程: ...
- 09--STL关联容器(map/multimap)
一:map/multimap的简介 map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对.它提供基于key的快速检索能力. map中key值是唯一的.集合中的元素按一定的顺 ...
- C++map类型
map是键-值对的集合,可以理解为关联数组,可以使用键作为下标来获取一个值 本文地址:http://www.cnblogs.com/archimedes/p/cpp-map.html,转载请注明源地址 ...
- Spring的IoC容器注入的类型
Spring除了可以注入Bean实例外,还可以注入其他数据类型. 注入基本数据类型 xml配置文件中的init-method="init"属性是取得Bean实例之后,输入属性值后自 ...
- map 类型
map 是键-值对的集合.map 类型通常可理解为关联数组(associative array): 可使用键作为下标来获取一个值,正如内置数组类型一样.而关联的本质在于元素的值与某个特定的键相关联,而 ...
- C++map类型 之 简单介绍
一:map的前世今生 (1)从关联容器与顺序容器说起.关联容器通过键(key)存储和读取元素.而顺序容器则通过元素在容器中的位置顺序存储和訪问元素(vector,queue,stack,list等). ...
- C++ Primer 有感(标准库map类型)
map是键-值对的集合.map类型通常可以理解为关联数组:可以使用键作为下标获取一个值,正如内置数组一样.而关联的本质在于元素的值于某个特定的键相关联,而并非通过元素在数组中的位置获取. 1.map对 ...
- Java中的集合(十四) Map的实现类LinkedHashMap
Java中的集合(十四) Map的实现类LinkedHashMap 一.LinkedHashMap的简介 LinkedHashMap是Map接口的实现类,继承了HashMap,它通过重写父类相关的方法 ...
随机推荐
- Extjs获取input值的几种方法
记录一下: ExtJs获取文本框中值的几种方式 EXTHTML 1.Html文本框 如: 获取值的方式为: var tValue = Ext.getDom('test').value; 或者 var ...
- UVA272-TEX Quotes(紫书例题3.1)
TeX is a typesetting language developed by Donald Knuth. It takes source text together with a few ty ...
- pytorch 3 activation 激活函数
2.3 Activation Function import torch import torch.nn.functional as F from torch.autograd import Vari ...
- java实现支付宝电脑支付(servlet版本)
前期准备: 蚂蚁金融开放平台 进行登录操作 进入我的开放平台 在上方找到沙箱,进入沙箱(网络编程虚拟执行环境). 这里的RSA2密钥设置下,我已经设置好了,所以便有了支付宝公钥(公钥是对外公开的,私钥 ...
- css清楚样式
- Java基础学习总结(56)——学java必知十大学习目标
诞生至今已有20年的Java,现在依然有很多人使用.回顾过去十五年的成果,Java一直是数一数二的.Java已经成为世界范围内应用最为广泛的编程语言之一.那么在学java的时候你知道到底要学什么吗?一 ...
- 洛谷 P1894 [USACO4.2]完美的牛栏The Perfect Stall
P1894 [USACO4.2]完美的牛栏The Perfect Stall 题目描述 农夫约翰上个星期刚刚建好了他的新牛棚,他使用了最新的挤奶技术.不幸的是,由于工程问题,每个牛栏都不一样.第一个星 ...
- 反射 + 配置文件 实现IOC容器
IOC实现: IOC容器我们只停留在知道上是不行的,我们要动手做印象对更深刻,那么我给大家看一个代码.看看代码中IOC容器的实现. 代码实现: 创建一个类库: 解决方式的类库建立: 创建一个实体类:U ...
- CxImage动态加载图片(判断图片文件类型)
1.打开一张图可以通过创建一个新的CxImage对象来完成,通过构造函数来打开一张图CxImage::CxImage(const char * filename, DWORD imagetype)其中 ...
- Laravel-HTTP-验证
Laravel-HTTP-验证 标签(空格分隔): php 第一种方式 **1 直接在controller里完成表单验证** **2 打印验证返回的错误信息 dd($errors)** 第二种方式 * ...