第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 上搭 ...
随机推荐
- 速战速决 (5) - PHP: 动态地创建属性和方法, 对象的复制, 对象的比较, 加载指定的文件, 自动加载类文件, 命名空间
[源码下载] 速战速决 (5) - PHP: 动态地创建属性和方法, 对象的复制, 对象的比较, 加载指定的文件, 自动加载类文件, 命名空间 作者:webabcd 介绍速战速决 之 PHP 动态地创 ...
- Java基本概念(2)J2EE里面的2是什么意思
J2EE里面的2是什么意思 J2SE,J2SE,J2ME中2的含义要追溯要1998年.1998年Java 1.2版本发布,1999年发布Java 1.2的标准版,企业版,微型版三个版本,为了区分这三个 ...
- 4、python列表
1.末尾追加:append() s = ["a", "b", "c"] print(s) #['a', 'b', 'c'] s.append ...
- Tomcat下使用c3p0配置jndi数据源
下载c3p0包: 下载地址:https://sourceforge.net/projects/c3p0/files/?source=navbar 解压后得到包:c3p0-0.9.2.jar,mchan ...
- 事件流之事件冒泡与事件捕获<JavaScript高级程序设计>学习笔记
1.事件流 浏览器开发团队遇到一个很有意思问题:页面的那一部分会拥有特定的事件? 对于理解这个问题您可以想象画在一张纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的其实不是一个圆,而是纸上 ...
- jquery自定义插件结合baiduTemplate.js实现异步刷新(附源码)
上一篇记录了BaiduTemplate模板引擎使用示例附源码,在此基础上对使用方法进行了封装 自定义插件jajaxrefresh.js 代码如下: //闭包限定命名空间 (function ($) { ...
- 用MSF进行提权
在WEB渗透中当我们拿到webshell了,我们可以试试用MSF(metasploit)来进行提权,在MSF里meterpreter很强大的! 我们先用msfvenom生成一个EXE的木马后门. ms ...
- SharePoint 2013 图文开发系列之自定义字段
SharePoint使用的优势,就在于开箱即用.快速搭建,SharePoint自身为我们提供了很多字段类型,已经很丰富了.但是,在实际应用中,我们还需要一些功能特殊的字段,下面,我们简单介绍下字段的开 ...
- android 自定义view中findViewById为空的解决办法
网上说的都是在super(context, attrs);构造函数这里少加了一个字段, 其实根本不只这一个原因,属于view生命周期的应该知道,如果你在 自定义view的构造函数里面调用findVie ...
- MVC学习系列1--什么是MVC
上面的虚线表示:被动角色.实线表示:主动角色. 1.控制器和视图:控制器和视图是双向的关系,但控制器的关系更主动. 当控制器是主动的角色的时候,控制器决定要显示哪一个View:当视图为主动角色时,视图 ...