我需要一个映射,其中键是唯一的,每个键都是一个包含3个数据项的自定义POD结构。这些值只是指向对象实例的指针。
从阅读docs for Qt's QMap vs QHash开始,好像我在地图中使用QSet作为关键字,然后我应该使用QHash,因为QSet提供operator==()
但不是{{1} }。这是一个公平的假设吗?但是,文档还说QHash需要一个名为qHash()的“全局qHash函数”,但我不清楚如何提供它,或者它是否是QSet的隐式部分?
如果我使用一个简单的结构作为我的密钥,我遇到了处理operator<()
的相同问题,尽管一个简单的POD结构应隐式具有qHash()
的可接受重载,它只是比较所有数据,对吗?
我对这里最好的方法有一些建议。
答案 0 :(得分:2)
我建议使用QHash
,除非您需要对键进行排序(我假设您没有)。
operator==
函数已由QSet
提供,假设由集合管理的类也定义了该运算符(所有基本数据类型和QString
等都有这一点)。
如果两组包含相同的元素,则认为它们相等。
此函数需要值类型来实现operator ==()。
您仍然需要提供qHash()
函数,该函数通常是这样定义的:
inline uint qHash( QSet<whatever> set )
{
return /* calculate a hash based on all the elements. */
}
只要定义QHash
的代码包含包含定义的文件,该定义就可以放在任何地方。如果您在此示例中为引用为whatever
的内容设置了自己的类,则可以使用该定义,例如在你的班级定义背后。
请注意,qHash
函数只需要确保等式obj1 == obj2
的结果始终等于qHash(obj1) == qHash(obj2)
的结果。
这意味着您不一定要生成唯一的哈希值,但文档中有以下注释:
但是,为了获得良好的性能,qHash()函数应该尝试尽可能为不同的键返回不同的哈希值。
我为一个存储字符串的集合编写了一个小测试应用程序:
#include <QtCore/QSet>
#include <QtCore/QHash>
#include <QtCore/QList>
#include <QtCore/QDebug>
typedef QSet<QString> QStringSet;
typedef QHash< QStringSet, QObject* > QStringSetToObjectHash;
inline uint qHash( const QStringSet mySet )
{
// convert the set to a list so we can sort and iterate over it
QList<QString> mySetAsList = mySet.toList();
qSort( mySetAsList );
// take the hash of the first item
uint result = qHash( mySetAsList.first() );
// for each remaining element in the list
for( int index = 1; index < mySetAsList.count(); index++ )
{
// XOR the current result with the hash of the next item
result ^= qHash( mySetAsList.at( index ) );
}
return result;
}
void insertIntoHash( QStringSetToObjectHash& hash, const QStringSet& key, QObject* const value )
{
qDebug() << "---------------------------------";
qDebug() << "Element hash value:" << qHash( key );
foreach( QStringSet existingKey, hash.keys() )
{
if( existingKey == key )
{
qDebug() << "Similar element found using == operator. QHash will not store that item twice";
}
}
hash.insert( key, value );
qDebug() << "QHash count:" << hash.count();
}
int main(int argc, char *argv[])
{
QStringSetToObjectHash testHash;
QObject dummy;
QStringSet testSet;
testSet.insert( "1" );
testSet.insert( "12" );
insertIntoHash( testHash, testSet, &dummy );
QStringSet testSet2( testSet );
insertIntoHash( testHash, testSet2, &dummy );
QStringSet testSet3;
testSet3.insert( "12" );
testSet3.insert( "1" );
insertIntoHash( testHash, testSet3, &dummy );
QStringSet testSet4;
testSet4.insert( "1" );
testSet4.insert( "2" );
testSet4.insert( "3" );
insertIntoHash( testHash, testSet4, &dummy );
}
这会产生以下输出:
---------------------------------
Element hash value: 883
QHash count: 1
---------------------------------
Element hash value: 883 Similar element found using == operator. QHash will not store that item twice
QHash count: 1
---------------------------------
Element hash value: 883 Similar element found using == operator. QHash will not store that item twice
QHash count: 1
---------------------------------
Element hash value: 48
QHash count: 2