Qt学习之路(37): Qt容器类之关联存储容器-程序员宅基地

技术标签: Qt  Blog  数据结构  

版权声明: 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。 http://devbean.blog.51cto.com/448512/248373
今天我们来说说Qt容器类中的关联存储容器。所谓关联存储容器,就是容器中存储的一般是二元组,而不是单个的对象。二元组一般表述为<Key-Value>,也就是“键-值对”。
首先,我们看看数组的概念。数组可以看成是一种<int-Object>形式的键-值对,它的Key只能是int,而值的类型是 Object,也就是任意类型(注意,这里我们只是说数组可以是任意类型,这个Object并不必须是一个对象)。现在我们扩展数组的概念,把Key也做 成任意类型的,而不仅仅是int,这样就是一个关联容器了。如果学过数据结构,典型的关联容器就是散列(Hash Map,哈希表)。Qt提供两种关联容器类型:QMap<K, T>和QHash<K, T>。
QMap<K, T>是一种键-值对的数据结构,它实际上使用跳表skip-list实现,按照K进行升序的方式进行存储。使用QMap<K, T>的insert()函数可以向QMap<K, T>中插入数据,典型的代码如下:
QMap<QString, int > map;
map.insert( "eins" , 1);
map.insert( "sieben" , 7);
map.insert( "dreiundzwanzig" , 23);
同样,QMap<K, T>也重载了[]运算符,你可以按照数组的复制方式进行使用:
map[ "eins" ] = 1;
map[ "sieben" ] = 7;
map[ "dreiundzwanzig" ] = 23;
[]操作符同样也可以像数组一样取值。但是请注意,如果在一个非const的map中,使用[]操作符取一个不存在的Key的值,则这个Key 会被自动创建,并将其关联的value赋予一个空值。如果要避免这种情况,请使用QMap<K, T>的value()函数:
int val = map.value( "dreiundzwanzig" );
如果key不存在,基本类型和指针会返回0,对象类型则会调用默认构造函数,返回一个对象,与[]操作符不同的是,value()函数不会创建一个新的键-值对。如果你希望让不存在的键返回一个默认值,可以传给value()函数第二个参数:
int seconds = map.value( "delay" , 30);
这行代码等价于:
int seconds = 30;
if (map.contains( "delay" ))
seconds = map.value( "delay" );
QMap<K, T>中的K和T可以是基本数据类型,如int,double,可以是指针,或者是拥有默认构造函数、拷贝构造函数和赋值运算符的类。并且K必须要重载<运算符,因为QMap<K, T>需要按K升序进行排序。
QMap<K, T>提供了keys()和values()函数,可以获得键的集合和值的集合。这两个集合都是使用QList作为返回值的。
Map是单值类型的,也就是说,如果一个新的值分配给一个已存在的键,则旧值会被覆盖。如果你需要让一个key可以索引多个值,可以使用QMultiMap<K, T>。这个类允许一个key索引多个value,如:
QMultiMap< int , QString> multiMap;
multiMap.insert(1, "one" );
multiMap.insert(1, "eins" );
multiMap.insert(1, "uno" );

QList<QString> vals = multiMap.values(1);
QHash<K, T>是使用散列存储的键-值对。它的接口同QMap<K, T>几乎一样,但是它们两个的实现需求不同。QHash<K, T>的查找速度比QMap<K, T>快很多,并且它的存储是不排序的。对于QHash<K, T>而言,K的类型必须重载了==操作符,并且必须被全局函数qHash()所支持,这个函数用于返回key的散列值。Qt已经为int、指针、 QChar、QString和QByteArray实现了qHash()函数。
QHash<K, T>会自动地为散列分配一个初始大小,并且在插入数据或者删除数据的时候改变散列的大小。我们可以使用reserve()函数扩大散列,使用 squeeze()函数将散列缩小到最小大小(这个最小大小实际上是能够存储这些数据的最小空间)。在使用时,我们可以使用reserve()函数将数据 项扩大到我们所期望的最大值,然后插入数据,完成之后使用squeeze()函数收缩空间。
QHash<K, T>同样也是单值类型的,但是你可以使用insertMulti()函数,或者是使用QMultiHash<K, T>类来为一个键插入多个值。另外,除了QHash<K, T>,Qt也提供了QCache<K, T>来提供缓存,QSet<K>用于仅存储key的情况。这两个类同QHash<K, T>一样具有K的类型限制。
遍历关联存储容器的最简单的办法是使用Java风格的遍历器。因为Java风格的遍历器的next()和previous()函数可以返回一个键-值对,而不仅仅是值,例如:
QMap<QString, int > map;
...
int sum = 0;
QMapIterator<QString, int > i(map);
while (i.hasNext())
sum += i.next().value();
如果我们并不需要访问键-值对,可以直接忽略next()和previous()函数的返回值,而是调用key()和value()函数即可,如:
QMapIterator<QString, int > i(map);
while (i.hasNext()) {
i.next();
if (i.value() > largestValue) {
largestKey = i.key();
largestValue = i.value();
}
}
Mutable遍历器则可以修改key对应的值:
QMutableMapIterator<QString, int > i(map);
while (i.hasNext()) {
i.next();
if (i.value() < 0.0)
i.setValue(-i.value());
}
如果是STL风格的遍历器,则可以使用它的key()和value()函数。而对于foreach循环,我们就需要分别对key和value进行循环了:
QMultiMap<QString, int > map;
...
foreach (QString key, map.keys()) {
foreach ( int value, map.values(key)) {
doSomething(key, value);
}
}

本文出自 “豆子空间 ” 博客,请务必保留此出处http://devbean.blog.51cto.com/448512/248373

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/iteye_20954/article/details/81898024

智能推荐

进程与线程的联系与区别_进程与线程的区别与联系-程序员宅基地

文章浏览阅读983次。一、基本概念_进程与线程的区别与联系

vue实现页面内容禁止选中,仅输入框和文本域可选_禁止输入框文件选中-程序员宅基地

文章浏览阅读7.9k次,点赞6次,收藏8次。上网上翻了翻,共找到两种方式CSS样式控制,只需将下面代码复制到 vue应用下,index.html文件中的body标签上*{ -webkit-touch-callout:none; /*系统默认菜单被禁用*/ -webkit-user-select:none; /*webkit浏览器*/ -khtml-user-select:none; /*早期浏览器..._禁止输入框文件选中

(笔记)微信开发笔记之微信授权_wxservice.checksignature false-程序员宅基地

文章浏览阅读802次。准备工作 申请一个微信测试号 下载一个内网穿透软件用于获取域名 我用的多 wenat软件诺依的开源项目微信授权接口配置位置测试号管理的接口配置中 此处使用内网穿透转换的域名/** * @desc: 门户入口 * @author: cao_wencao * @date: 2019-09-02 17:06 */@Slf4j@AllArgsConstructor@Rest..._wxservice.checksignature false

简单说说NVMe 2.0协议_nvme2.0-程序员宅基地

文章浏览阅读5.7k次,点赞2次,收藏21次。简单介绍一下2022年1月最新的NVMe协议_nvme2.0

微信公众号只能设置两个网页授权域名的解决方案-程序员宅基地

文章浏览阅读5.1k次,点赞2次,收藏10次。中转站index.php<?phpif(isset($_GET['param']) && !empty($_GET['param'])){ $param = urldecode($_GET['param']); if(!strpos($param, '?')){ $action = "huidiao.php?param=" .$param.'?1=1'; }else{ $action = "huidiao.php?par

完整版:献给初学者的Java学习方法-程序员宅基地

文章浏览阅读77次。2019独角兽企业重金招聘Python工程师标准>>> ..._java给初学者最好理解的讲义

随便推点

Unity按键设置-InputManager_unity axis snap-程序员宅基地

文章浏览阅读9.9k次,点赞3次,收藏15次。unity的Axis设置,路径为Edit-&gt;Project setting-&gt;Input:属性如下:Name:【按键名】该键的名称,可以在脚本编程中直接引用他。比如:Input.GetButtonDown(“Jump”);Descriptive Name:【描述名】在游戏的独立机构中的配置对话框中,当控制值为正时候所显示的名称。默认空白。Negative Descrip..._unity axis snap

QML自定义Qt Quick Controls 2 样式之 RadioButton_qml radiobutton 自定义-程序员宅基地

文章浏览阅读3k次。近期学习Qt,记录下学习过程,以免忘记。操作环境 WIN7+Qt 5.12.0。新建资源目录 controls,新建 RadioButton.qml文件。RaidoButton包含三个可视项目:background, content item 和 indicator,在默认样式文件中复制相关代码。默认样式文件路径:$QTDIR/qml/QtQuick/Controls.2/RadioButt..._qml radiobutton 自定义

类模板分文件编写遇到的问题和解决方法_类模板函数分文件时为什么调用不到-程序员宅基地

文章浏览阅读425次。1.问题引入: 当使用类模板的成员函数的具体实现与声明分别写在不同的文件时,出现错误,使用vs作为IDE。错误代码:main.cpp#include"person.h"void test01() { Person<string, int> p("赵云", 38); p.showPerson();}int main() { test01(); return 0;..._类模板函数分文件时为什么调用不到

豆沙绿色值---全_豆沙绿参数-程序员宅基地

文章浏览阅读6.9k次。豆沙绿的参数为:a. RGB颜色:(199,237,204)b. 十六位颜色代码:C7EDCCc. 色调(Hue)85、饱和度(Sat)123、亮度(Lum)205------------- The End -------------许可协议: 转载请保留原文链接及作者。..._豆沙绿参数

HBase在微博搜索业务中的应用-程序员宅基地

文章浏览阅读1k次。在社交媒体平台的发展过程中,越来越多的人依赖于微博进行信息的传播、分享。不仅如此,微博作为新浪等知名门户网站的基础服务,有着独特的特性。比如,它是一个高度互联网化的信息流通工具,用户可以自由的发布或转发微博内容,并且具有大量的搜索功能。因此,为微博搜索服务提供更加高效、精准的结果,帮助用户找到想要的内容,也成为各大互联网公司关注的一个重点方向。在微博搜索服务中,通常会采用基于搜索引擎的关键词匹配方式,通过检索用户输入的关键字,返回包含相关主题信息的微博条目。

centos6安装并配置zabbix3.2_centos6配置zabbix-程序员宅基地

文章浏览阅读274次。1.安装PHPZabbix 3以后对PHP的要求最低为5.4,而CentOS6默认为5.3.3,完全不满足要求,故需要利用第三方源,将PHP升级到5.4以上,注意,不支持PHP7rpm -ivh http://repo.webtatic.com/yum/el6/latest.rpmyum install -y php56w php56w-gd php56w-mysql php56w-bcma..._centos6配置zabbix

推荐文章

热门文章

相关标签