StupidBeauty
Read times:1779Posted at:Wed Jul 5 06:45:21 2023 - no title specified

Qt 6.5文档翻译:QMap类,QMap Class

template <typename Key, typename T> class QMap

QMap类,是一个模板类,它提供了关联数组的功能。 详细说明……

头文件:

#include <QMap>

CMake指令:

find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)

qmake指令:

QT += core

注意:这个类中的所有函数都是 可重入的

详细说明

QMap<Key, T>是Qt 中的一个通用的 容器类 。它能够储存键值对((key, value) pairs),并支持通过键(key)来快速查询。

QMap和QHash的功能类似。它们的差异在于:

  • •. QHash的平均查询速度比QMap 要快。(参考 算法复杂度 以了解更多。)

  • •.当你在QHash中遍历时,具体的条目的顺序是随机的。而在QMap中,条目一定是按照键来排序的。

  • •. QHash中的键的类型,必须实现operator==()方法,并且要有一个全局的qHash(Key)函数。QMap 中的键的类型,必须实现operator<()方法,以支持整体排序。从Qt 5.8.1开始,可以安全地使用指针类型作为键,即使其提供的operator<()方法不能支持整体排序也没关系。

以下是一个QMap 示例,使用字符串(QString)作为键,使用整数(int)作为值:

QMap < QString , int > map;

要向映射中插入一个键值对,你可以使用operator[]()方法:

map[ "one" ] = 1 ;

map[ "three" ] = 3 ;

map[ "seven" ] = 7 ;

以上代码,会向这个 QMap 中插入以下三个键值对:("one", 1)、("three", 3)和("seven", 7)。另一个向映射中插入条目的方法就是insert():

map.insert( "twelve" , 12 );

要查询一个值,可以使用operator[]()或value():

int num1 = map[ "thirteen" ];

int num2 = map.value( "thirteen" );

如果在映射中当前并不存在与指定的键相对应的条目,那么,这些方法会返回一个 默认值

要检查映射中是否包含某个特定的键,可以使用contains():

int timeout = 30 ;

if (map.contains( "TIMEOUT" ))

timeout = map.value( "TIMEOUT" );

另外还有一个重载的value()方法,在未能找到与指定的键相关联的条目时,会使用它的第二个参数作为默认值来返回:

int timeout = map.value( "TIMEOUT" , 30 );

通常情况下,我们建议你使用contains()和value()来查询映射中的某个键,而不是使用operator[]()。原因是,如果当前没有条目与指定的键相关联,那么operator[]()会默默地向映射中插入一个条目(除非这个映射本身是常量)。例如,以下代码片断,会在内存中创建1000个条目:

// 错误做法

QMap < int , QWidget *> map;

...

for ( int i = 0 ; i < 1000 ; ++i) {

if (map[i] == okButton)

cout << "Found button at index " << i << endl;

}

要避免这个问题的话,应当在上面的代码中,将map[i]替换成map.value(i)

要想遍历QMap 中储存的所有键值对,可以使用一个迭代器。QMap同时提供了Java 风格的迭代器 (QMapIteratorQMutableMapIterator)以及 标准模板库风格的迭代器 (QMap::const_iteratorQMap::iterator)。以下是使用Java 风格迭代器来遍历一个QMap<QString, int>的示例:

QMapIterator < QString , int > i(map);

while (i.hasNext()) {

i. next ();

cout << qPrintable (i.key()) << ": " << i.value() << endl;

}

以下代码,做的相同的事情,不过使用的是标准模板库风格的迭代器:

for ( auto i = map.cbegin(), end = map.cend(); != end ; ++i)

cout << qPrintable (i.key()) << ": " << i.value() << endl;

那些条目,会被按照键类型的从小到大的顺序来遍历。

在QMap中,对于特定的键,只允许有一个对应的值。如果你调用insert(),并且指定一个已经存在于 QMap 中的键,那么,之前设置的值会被删除。例如:

map.insert( "plenty" , 100 );

map.insert( "plenty" , 2000 );

// map.value("plenty") == 2000

不过,在QMultiMap中,你可以针对单个键存储多个值。

如果你只是需要从映射中获取那些值(而不关心键),那么,可以使用基于范围的for 循环:

QMap < QString , int > map;

...

for ( int value : std::as_const(map))

cout << value << endl;

有多种方法,可以用于从映射中删除条目。其中一种方法就是调用remove();这会删除与指定的键相关联的任何条目。也可以调用QMutableMapIterator::remove()。另外,可以调用clear()来清空整个映射。

在QMap中,键和值的数据类型都必须是 可赋值的数据类型 。这已经包含了你通常会用到的大部分数据类型了,不过,要注意,某些类型是不被编译器允许使用的,例如,你不能将QWidget作为值来使用;而是应当使用QWidget *。另外,QMap中的键类型,必须提供operator<()方法。QMap使用这个方法来确保它的条目是处于排序状态的,并且它假设,对于两个键xy来说,如果x < yy < x都不为真(true),那么,这两个键是等同的。

示例:

#ifndef EMPLOYEE_H

#define EMPLOYEE_H

class Employee

{

public :

Employee () {}

Employee ( const QString &name, QDate dateOfBirth);

...

private :

QString myName;

QDate myDateOfBirth;

};

inline bool operator <( const Employee &e1, const Employee &e2)

{

if (e1.name() != e2.name())

return e1.name() < e2.name();

return e1.dateOfBirth() < e2.dateOfBirth();

}

#endif // EMPLOYEE_H

在这个示例中,我们首先比较两个雇员的名字。如果名字是相同的,那么,我们比较两个雇员的生日,以期望分个先后出来。

参考QMapIteratorQMutableMapIteratorQHashQSet

成员函数文档

QMap::const_iterator QMap::cbegin() const

返回一个常量的 标准模板库风格的迭代器 ,指向映射中的第一个条目。

参考begin() 和cend()。

QMap::const_iterator QMap::cend() const

返回一个常量的 标准模板库风格的迭代器 指向映射中最后一个实际条目之后的那个虚构的条目。

参考cbegin()和end()。

QMap::size_type QMap::count() const

这是一个重载函数。

size()相同。

QMap::iterator QMap::insert(const Key &key, const T &value)

插入一个新的条目,以key作为键,以value作为值。

如果已有某个条目与键key相关联,那么,它的值会被替换为value。

参考QMultiMap::insert()。

QMap::iterator QMap::insert(QMap::const_iterator pos, const Key &key, const T &value)

这是一个重载函数。

插入一个新的条目,以key作为键,以value作为值,并且以提示的位置pos作为建议的插入位置。

如果使用constBegin()作为提示位置,那就是表示,此处的键key比映射中的任何键都要小。类似地,如果使用constEnd()作为提示位置,那就是表示,此处的键key比映射中的任何键都要(严格地)大。在其它情况下,提示位置必须符合这个条件:(pos - 1).key() < key <= pos.key()。如果提示位置pos是错误的,那么它会被忽略,进而执行一个常规的插入操作。

如果已有某个条目与键key相关联,那么,它的值会被替换为value。

如果提示位置是正确的,并且该映射当前未被共享,那么,此次插入动作的执行时间会是均摊的(amortized 常量时间

当你需要基于一组已排序的数据来创建一个映射时,以constBegin()作为提示位置并且从最大的那个键开始插入,要比以constEnd()作为提示位置并且按照从小到大的顺序来插入要快一些。因为,constEnd() - 1(在检查提示位置是否有效时执行)需要 对数时间

注意:谨慎使用提示位置参数。如果你将某个旧的共享的映射实例中的迭代器作为参数提供到这里,可能导致崩溃,也可能,在不崩溃的情况下默默地损坏当前映射和pos参数所从属的那个映射。

参考QMultiMap::insert()。

Key QMap::key(const T &value, const Key &defaultKey = Key()) const

这是一个重载函数。

返回第一个与值value相关联的键,或是,如果映射中不包含其值为value的条目,则返回默认键defaultKey。如果未提供默认键参数defaultKey,则在对应的情况下这个函数会返回一个 默认构造的键

这个函数可能会很慢( 线性时间 ),因为QMap的内部数据结构是针对基于键的快速查询而优化的,而非针对基于值的快速查询而优化的。

参考value()和keys()。

QList<Key> QMap::keys() const

返回一个列表,其中会包含这个映射中所有的键,并且以递增顺序排列。

其顺序会确保与values()中使用的顺序相同。

这个函数会在 线性时间 内创建一个新的列表。对于这个过程中所必须耗费的时间和内存,可通过从keyBegin()遍历到keyEnd()来避免。

参考QMultiMap::uniqueKeys()、values()和key()。

QList<Key> QMap::keys(const T &value) const

这是一个重载函数。

返回一个列表,其中包含所有与值value相关联的键,并且以递增顺序排列。

这个函数可能会很慢( 线性时间 ),因为QMap的内部数据结构是针对基于键的快速查询而优化的,而非针对基于值的快速查询而优化的。

QMap::size_type QMap::remove(const Key &key)

删除映射中所有与键key相关联的条目。返回所删除的条目的个数,如果键存在则是1,否则则是0。

参考clear()和take()。

QMap::size_type QMap::size() const

返回映射中键值对的个数。

参考isEmpty()和count()。

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands