第37课 深度解析QMap与QHash
1. QMap深度解析
(1)QMap是一个以升序键顺序存储键值对的数据结构
①QMap原型为 class QMap<K, T>模板
②QMap中的键值对根据Key进行了排序
③QMap中的Key类型必须重载operator< 。(即“小于”操作符)
(2)QMap使用示例1
QMap<QString, int> map; //注意插入时是无序的 map.insert(); map.insert(); map.insert(); ; i<; i++) { //通过键取值 qDebug() << map.value("key " + QString::number(i)); } //注意map中的key会被升序排序 QList<QString> list = map.keys(); ; i<list.count(); i++) { qDebug() << list[i]; }
(3)QMap使用示例2:用数组方式或迭代器方式访问
QMap<QString, int> map; //以数组方式存取,注意输入时为无序的 map[; map[; map[; ; i<; i++) { //以数组方式取值 qDebug() << map["key " + QString::number(i)]; } //it可看到一个指针,指向第1个元素之前。 QMapIterator<QString, int> it(map); while(it.hasNext()) { it.next(); qDebug() << it.key() << " : " << it.value(); }
(4)QMap的注意事项
①通过Key获取Value时:
A.当Key存在时:返回对应的Value;
B.当Key不存在时:返回值类型所对应的“零”值
②插入键值对时
A.当Key存在时:更新Value的值
B.当Key不存在时:插入新的键值对
【编程实验】QMap使用体验
#include <QCoreApplication> #include <QMap> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QMap<QString, int> map; //插入键值对,注意,插入操作是无序的,存入后会被自动升序排序。 map.insert(); map.insert(); map.insert(); //取出所有的键(经过排序的) QList<QString> kList = map.keys(); ; i<kList.count(); i++) { qDebug() << kList[i];//注意,输出元素是升序排列的 } //取出所有的值(根据key排序过的顺序) QList<int> vList = map.values(); ; i<vList.count(); i++) { qDebug() << vList[i];//注意,输出元素是根据key排序过的 } //通过迭代器遍历 QMapIterator<QString, int> it(map); //it指针第1个元素之前的位置 while(it.hasNext()) { it.next(); qDebug() << it.key() << " : " << it.value(); } return a.exec(); } /*输出结果: "key 0" "key 1" "key 2" 0 1 2 "key 0" : 0 "key 1" : 1 "key 2" : 2 */
2. QHash深度解析
(1)QHash是Qt中的哈希数据结构
①QHash原型为class QHash<K, T>模板
②QHash中的键值对在内部无序排列。注意QMap是升序排序的!
③QHash的Key类型必须重载operator==。(即“相等”操作符)
④QHash中的Key对象必须重载全局哈希函数qHash()。
(2)QHash使用示例
QHash<QString, int> hash; //以数组方式存取,注意输入时为无序的 hash[; hash[; hash[; QHash<QString, int>::const_iterator i; //const_iterator为内部类 for(int i=hash.constBegin(); i!= hash.constEnd(); ++i) { qDebug() << i.key() << " :" << i.value(); } //it可看到一个指针,指向第1个元素之前。 QMapIterator<QString, int> it(map); while(it.hasNext()) { it.next(); qDebug() << it.key() << " : " << it.value(); }
【编程实验】QHash使用体验
#include <QCoreApplication> #include <QHash> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QHash<QString, int> hash; //插入键值对,注意,插入操作是无序的,但存入后不会自动排序。 hash.insert(); hash.insert(); hash.insert(); //取出所有的键 QList<QString> kList = hash.keys(); ; i<kList.count(); i++) { qDebug() << kList[i]; } //取出所有的值 QList<int> vList = hash.values(); ; i<vList.count(); i++) { qDebug() << vList[i]; } hash[; //通过数组方式存入键值对 //通过迭代器遍历 QHash<QString, int>::const_iterator it; for(it = hash.constBegin(); it != hash.constEnd(); ++it) { qDebug() << it.key() << " : " << it.value(); } return a.exec(); } /*输出结果: "key 2" "key 0" "key 1" 2 0 1 "key 2" : 2 "key 4" : 4 "key 0" : 0 "key 1" : 1 */
(3)QMap和QHash接口的比较
QMap |
QHash |
|
接口 |
接口相同,可直接替换使用 |
|
查找速度 |
较慢 |
快 |
占用存储空间 |
较小 |
大 |
元素存储 |
以Key的升序存领储 |
任意的方式 |
键类型必须重载的函数 |
Operator<()函数 |
Operator==()和qHash(Key)函数 |
【编程实验】文本编辑器程序中的文件后缀名映射
//处理后缀的代码
QString MainWindow::showFileDialog(QFileDialog::AcceptMode mode, QString title) { QString ret = ""; QFileDialog fd(this); QStringList filters; QMap<QString, QString> map; ] = { {"Text(*.txt)", ".txt"}, {"All Files(*.*)", "*" }, {NULL, NULL} }; ; filterArray[i][] != NULL; i++) { filters.append(filterArray[i][]); map.insert(filterArray[i][], filterArray[i][]); } fd.setWindowTitle(title); fd.setAcceptMode(mode); //QFileDialog::AcceptOpen或AcceptSave fd.setNameFilters(filters); if(mode == QFileDialog::AcceptOpen) { fd.setFileMode(QFileDialog::ExistingFile); //打开文件必须存在! } if(fd.exec() == QFileDialog::Accepted) { ret = fd.selectedFiles()[]; //Qt5中ret返回的是完整的路径名,含后缀。因此,后面的if块可省略,但Qt4可能 //会返回不带后缀的文件名,当保存文件时,须手动加上去。 if(mode == QFileDialog::AcceptSave) { QString postfix = map[fd.selectedNameFilter()]; if((postfix != "*") && !ret.endsWith(postfix)) { ret = ret + postfix; } } } return ret; }
//完整的MainWindowSlots.cpp代码
//该文件MainWindowSlots.cpp与MainWindowUI.cpp的分离 //体现了界面和功能代码分离的思想 #include "MainWindow.h" #include <QMessageBox> #include <QFile> #include <QTextStream> #include <QMap> #include <QDebug> void MainWindow::showErrorMessage(QString message) { QMessageBox msg(this); msg.setWindowTitle("Erro"); msg.setText(message); msg.setIcon(QMessageBox::Critical); msg.setStandardButtons(QMessageBox::Ok); msg.exec(); } int MainWindow::showQueryMessage(QString message) { QMessageBox msg(this); msg.setWindowTitle("Query"); msg.setText(message); msg.setIcon(QMessageBox::Question); msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); return msg.exec(); } QString MainWindow::showFileDialog(QFileDialog::AcceptMode mode, QString title) { QString ret = ""; QFileDialog fd(this); QStringList filters; QMap<QString, QString> map; ] = { {"Text(*.txt)", ".txt"}, {"All Files(*.*)", "*" }, {NULL, NULL} }; ; filterArray[i][] != NULL; i++) { filters.append(filterArray[i][]); map.insert(filterArray[i][], filterArray[i][]); } fd.setWindowTitle(title); fd.setAcceptMode(mode); //QFileDialog::AcceptOpen或AcceptSave fd.setNameFilters(filters); if(mode == QFileDialog::AcceptOpen) { fd.setFileMode(QFileDialog::ExistingFile); //打开文件必须存在! } if(fd.exec() == QFileDialog::Accepted) { ret = fd.selectedFiles()[]; //Qt5中ret返回的是完整的路径名,含后缀。因此,后面的if块可省略,但Qt4可能 //会返回不带后缀的文件名,当保存文件时,须手动加上去。 if(mode == QFileDialog::AcceptSave) { QString postfix = map[fd.selectedNameFilter()]; if((postfix != "*") && !ret.endsWith(postfix)) { ret = ret + postfix; } } } return ret; } void MainWindow::preEditorChanged() { if (m_isTextChanged) { int r = showQueryMessage("Do you want to save the changes to file?"); switch(r) { case QMessageBox::Yes: saveCurrentData(m_filePath); break; case QMessageBox::No: m_isTextChanged = false; break; case QMessageBox::Cancel: break; } } } void MainWindow::onFileNew() { preEditorChanged(); if(!m_isTextChanged) { mainEditor.clear(); setWindowTitle("NotePad - [ New ]"); m_filePath = ""; m_isTextChanged = false; } } void MainWindow::onFileOpen() { preEditorChanged(); if( !m_isTextChanged) { QString path = showFileDialog(QFileDialog::AcceptOpen, "Open"); if( path != "") { QFile file(path); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { mainEditor.setPlainText(QString(file.readAll())); file.close(); m_filePath = path; //记录当前打开的文件路径和文件名 m_isTextChanged = false; setWindowTitle("NotePad - [" + m_filePath + "]"); } else { showErrorMessage(QString("Open file Error!\n\n") + "\"" + path + "\""); } } } } QString MainWindow::saveCurrentData(QString path, QString title) { QString ret = path; if (ret =="") { //执行下面语句时,用户可以点击“取消”,此时ret返回"" ret = showFileDialog(QFileDialog::AcceptSave, title); } if (ret != "") { QFile file(ret); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); out << mainEditor.toPlainText(); file.close(); setWindowTitle("NotePad - [" + ret + "]"); m_isTextChanged = false; //己保存 } else { showErrorMessage(QString("Save file Error!\n\n") + "\"" + m_filePath + "\""); ret =""; //保存失败时 } } return ret; } void MainWindow::onFileSave() { QString path = saveCurrentData(m_filePath, "Save"); if( path != "" ) { m_filePath = path; } } void MainWindow::onFileSaveAs() { QString path = saveCurrentData(m_filePath, "Save As"); if( path != "" ) { m_filePath = path; } } void MainWindow::onTextChanged() { if( !m_isTextChanged ) { setWindowTitle("*" + windowTitle()); } m_isTextChanged = true; //qDebug()<< "onTextChanged()"; }
3. 小结
(1)Qt中提供了用于存储键值对的类模板
(2)QHash和QMap遵循相同的使用接口
(3)QHash的查找速度快于QMap
(4)QMap需要的内存空间低于QHash
(5)QHash对于Key类型的要求高于QMap。(QHash要求key类型操作两个操作符函数)
第37课 深度解析QMap与QHash的更多相关文章
- Kafka深度解析
本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/01/02/Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅 ...
- 深度解析SDN——利益、战略、技术、实践(实战派专家力作,业内众多专家推荐)
深度解析SDN——利益.战略.技术.实践(实战派专家力作,业内众多专家推荐) 张卫峰 编 ISBN 978-7-121-21821-7 2013年11月出版 定价:59.00元 232页 16开 ...
- mybatis 3.x源码深度解析与最佳实践(最完整原创)
mybatis 3.x源码深度解析与最佳实践 1 环境准备 1.1 mybatis介绍以及框架源码的学习目标 1.2 本系列源码解析的方式 1.3 环境搭建 1.4 从Hello World开始 2 ...
- Kafka深度解析(如何在producer中指定partition)(转)
原文链接:Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅的消息系统.主要设计目标如下: 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能 ...
- 《SEO深度解析——全面挖掘搜索引擎优化的核心秘密》
<SEO深度解析——全面挖掘搜索引擎优化的核心秘密> 基本信息 作者: 痞子瑞 出版社:电子工业出版社 ISBN:9787121224041 上架时间:2014-2-28 出版日期:201 ...
- linux ssh使用深度解析(key登录详解)
linux ssh使用深度解析(key登录详解) SSH全称Secure SHell,顾名思义就是非常安全的shell的意思,SSH协议是IETF(Internet Engineering Task ...
- 程序员收藏必看系列:深度解析MySQL优化(二)
程序员收藏必看系列:深度解析MySQL优化(一) 性能优化建议 下面会从3个不同方面给出一些优化建议.但请等等,还有一句忠告要先送给你:不要听信你看到的关于优化的“绝对真理”,包括本文所讨论的内容,而 ...
- Flink 源码解析 —— 深度解析 Flink 是如何管理好内存的?
前言 如今,许多用于分析大型数据集的开源系统都是用 Java 或者是基于 JVM 的编程语言实现的.最着名的例子是 Apache Hadoop,还有较新的框架,如 Apache Spark.Apach ...
- Flink 源码解析 —— 深度解析 Flink 序列化机制
Flink 序列化机制 https://t.zsxq.com/JaQfeMf 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- Mac 上搭 ...
随机推荐
- C++_系列自学课程_第_10_课_表达式_《C++ Primer 第四版》
程序设计语言中大部分程序都在进行表达式的求值操作, 例如求两个数的和,求一个表达式的逻辑结果,或者通过输入输出表达式语句进行输入和输出. 这里我们对表达式进行讨论. 一.表达式 1.表达式 表达式由一 ...
- Scalaz(56)- scalaz-stream: fs2-安全运算,fs2 resource safety
fs2在处理异常及资源使用安全方面也有比较大的改善.fs2 Stream可以有几种方式自行引发异常:直接以函数式方式用fail来引发异常.在纯代码里隐式引发异常或者在运算中引发异常,举例如下: /函数 ...
- tet
施大峰[[昂司法部]]... [[分公司电饭煲]]
- MySQL字符串替换与HTML转义
ps:今天遇到一个问题,从数据库读取一个字符串,然后在jsp用EL表达式显示时,因为数据库原始数据是带有HTML标签的,所以显示的时候会把标签直接转换成HTML,但是我想要的是HTML标签字符串,所以 ...
- IOS开发基础知识--碎片40
1:Masonry快速查看报错小技巧 self.statusLabel = [UILabel new]; [self.contentView addSubview:self.statusLabel]; ...
- iOS 系统分析(一) 阅读内核准备知识
➠更多技术干货请戳:听云博客 0x01 iOS体系架构 1.1 iOS 系统的整体体系架构 用户体验( The User Experience layer ):SpringBoard 同时支持 Spo ...
- 2016年4月21百度iOS实习生在线笔试题&编程题
1.一个人上台阶可以一次上1个,2个,或者3个,问这个人上32层的台阶,总共有几种走法? 思路:先建立数学模型,设3步的走 i 次,2步的走 j 次, 1步的走 k 次,上了3*i + 2*j + 1 ...
- C#命名规则和编码规范
用Pascal规则来命名属性.方法.事件和类名. public class HelloWorld { public void SayHello(string name) { } } Pascal规则是 ...
- linux 学习随笔-压缩和解压缩
.gz 由gzip压缩工具压缩的文件 .bz2 由bzip2压缩工具压缩的文件 .tar 由tar打包程序打包的文件 .tar.gz 先由tar打包,gzip压缩 .tar.bz2 先由tar打包,b ...
- ant+findbugs 扫描代码生成报告
1. 下载安装ant.findbugs 下载ant.findbugs最新压缩包解压到本地磁盘合适位置,比如: D:\Program Files\apache-ant-1.9.7 D:\Program ...