Qt中关联容器(容器存储的是<键,值>对)有:QMap(skip-list-based字典)、QMultiMap、QHash(哈希表)、QMultiHash、QSet
关联容器的引入:
首先,我们看看数组的概念。数组可以看成是一种<int-Object>形式的键-值对,它的Key只能是int,而值的类型是Object,也就是任意类型(注意,这里我们只是说数组可以是任意类型,这个Object并不必须是一个对象)。现在我们扩展数组的概念,把Key也做成任意类型的,而不仅仅是int,这样就是一个关联容器了。
QMap skip-list-based字典:
1、QMap<K, T>是一个以升序键顺序存储键值对的容器
2、QMap<K, T>重载了operator[],可以以数组的方式使用QMap<K,T>
3、QMap<K, T>中的k与T可以是基本数据类型,也可以是类类型
注意事项:
1、 之前说过容器内存储元素的要求,k与T必须都满足要求,同时,如果k是类类型,必须提供重载的operator<
2、 QMap<K, T>如果是non-const的,使用operator[]操作的k获取T时,如果k存在,返回对应T,如果k不存在,则会用给定的k和T对应的”零”值创建一个新项,并返回T对应的”零”值
3、 使用成员
const T | value ( const Key & key ) const |
可以避免意外地创建”零”值,如果K不存在,返回T对应的”零”值,但不会创建新项
4、 K与T的映射一般是单一的:当插入键值对时,如果k存在,更新T的值,当K不存在,插入新的键值对
5、想要一个K对应多个T,使用QMulitMap类或成员函数
iterator | insertMulti ( const Key & key, const T & value ) |
#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QMap>
#include <QMapIterator>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QMap<QString, int> map;
map.insert("key 2", 2); //故意逆k插入键值对
map.insert("key 1", 1);
map.insert("key 0", 0);
QList<QString>kList = map.keys(); //获取全部键
for(int i=0; i<kList.count(); i++)
{
qDebug() << kList[i];
}
QList<int> vList = map.values(); //获取全部值
for(int i=0; i<vList.count(); i++)
{
qDebug() << vList[i];
}
QMapIterator<QString, int> it(map); //迭代器指向map的第一个元素的前一个位置(java风格迭代器)
while( it.hasNext() )
{
it.next(); //指向第一个元素
qDebug() << it.key() << " : " << it.value();
}
return a.exec();
}
QHash(哈希表):
1、QHash<K, T>中的键值对在内部无序排列
2、QHash<K, T>重载了operator[],可以以数组的方式使用QHash<K,T>
3、QHash<K, T>中的k与T可以是基本数据类型,也可以是类类型
4、QHash<K, T>为其内部的哈希表自动分配最初存储区域并在有元素插入或删除时重新划分所分配存储区域大小
注意事项:
1、 之前说过容器内存储元素的要求,k与T必须都满足要求,同时,如果k是类类型,必须提供重载的operator=
2、 必须提供了重载的全局函数qHash()以返回键的哈希值,Qt已经提供了支持整型、指针型、QChar、QString以及QByteArray的全局qHash()函数
3、 如果non-const,使用operator[]时,K不存在会有与QMap<K,T>同样的问题,且解决办法相同
4、 K与T的映射一般是单一的:当插入键值对时,如果k存在,更新T的值,当K不存在,插入新的键值对
5、想要一个K对应多个T,使用QMultiHash类或成员函数
iterator | insertMulti ( const Key & key, const T & value ) |
6、一般,先以我们期望的最大值为参数调用成员函数
void | reserve ( int size ) |
后插入元素,最后调用成员函数
void | squeeze () |
以减少QHash<K, T>的内存使用,调整性能
#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QHash>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QHash<QString, int> hash;
hash.insert("key 2", 2); //插入键值对
hash.insert("key 1", 1);
hash.insert("key 0", 0);
QList<QString> kList = hash.keys(); //获取全部键
for(int i=0; i<kList.count(); i++)
{
qDebug() << kList[i];
}
QList<int> vList = hash.values(); //获取全部值
for(int i=0; i<vList.count(); i++)
{
qDebug() << vList[i];
}
hash["key 4"] = 4;
QHash<QString, int>::const_iterator i; // STL_Styl风格迭代器
for(i=hash.constBegin(); i!=hash.constEnd(); ++i) //constBegin指向第一个元素,constEnd指向最后一个元素的尾后
{
qDebug() << i.key() << " : " << i.value();
}
return a.exec();
}
QSet:
QSet<K>仅存储键,其内部依赖于QHash<K,T>
QMap<K, T>与QHash<K, T>对比分析
QMap<K, T>和QHash<K, T>接口相同,可直接替换使用
1、 QHash<K, T>的查找速度明显快于QMap<K, T>
2、 QHash<K, T>占用的存储空间明显多于QMap<K, T>
3、 QHash<K, T>以任意方式存储元素
4、 QMap<K, T>以K顺序存储元素
5、 Qhash<K, T>的K类型必须提供operator=与全局函数qHash()
6、 QMap<K, T>的键类型必须提供函数operator<