QHash方法功能(QT5.12)

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include<QHash>
#include<QDebug>
#include<QList>
#include<QPair>

//QHash类是一个模板类,提供基于哈希表的字典。
//QHash<Key,T>是Qt的通用容器类之一。它存储(键、值)对,并提供与键关联的值的快速查找。
//QHash提供了比QMap更快的查找速度。
//在QMap上迭代时,项目总是按键排序。使用QHash,项目可以任意排序。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QHash<QString, int> hash; //定义hash对象,要定义键和值的类型
    hash.clear(); //清除整个对象
    hash["one"] = 2;
    hash["three"] = 3;
    hash["seven"] = 7;
    hash["seven"] = 9;
    hash["eight"] = 9;
    qDebug()<<hash.capacity(); //返回QHash内存。
    qDebug()<<hash.contains("three"); //查询指定键名是否存在
    qDebug()<<hash.count(); //查询表中的条目个数
    qDebug()<<hash.count("seven"); //返回与键关联的项数。
    qDebug()<<hash.empty(); //如果哈希为空,则返回true;否则返回false。
    qDebug()<<hash.isEmpty(); //如果哈希为空,则返回true;否则返回false。
    qDebug()<<hash.key(2); //根据值返回当前键值
    qDebug()<<hash.key(9,"new");//根据值返回当前键值 如果不存在就返回参数2的key

    QList<QString> keys = hash.keys(); //获取键值列表
    qDebug()<<hash.remove("one"); //删除指定键值的键值对,返回删除个数
    hash.reserve(100);//设置hash的大小(一般不用,hash有自己的算法修改长度)
    qDebug()<<hash.size(); //返回散列中的项数。
    hash.squeeze(); //减少QHash内部哈希表的大小以节省内存。(一般不用)
    QHash<QString, int> H2;
    hash.swap(H2); //交换两个hash对象
    qDebug()<<hash.take("three"); //从散列中删除带有密钥的项,并返回与之关联的值。不需要返回值就使用remove
    keys = hash.uniqueKeys();//返回包含映射中所有键的列表。在映射中多次出现的键在返回的列表中只出现一次。
    QHash<QString, int> H3;
    H3 = hash.unite(H2);//将另一个哈希中的所有项插入到此哈希中。如果两个散列共用一个键,则生成的散列将多次包含该键。
    qDebug()<<hash.value("seven"); //返回与键关联的值。
    qDebug()<<hash.value("seven", 0); //返回与键关联的值。 没有则返回参数2的值
    QList<int> values = hash.values(); //获取值列表
    values = hash.values("seven"); //返回与键关联的所有值的列表,从最近插入的值到最近插入的值。

    //迭代器
    hash.clear();
    hash["one"] = 1;
    hash["two"] = 2;
    hash["three"] = 3;
    hash["four"] = 4;
    hash["five"] = 5;
    hash["six"] = 5;
    hash["seven"] = 5;
    hash["seven"] = 7;

    QHash<QString, int>::iterator it = hash.begin(); //返回指向散列中第一项的STL样式迭代器。
    it = hash.end(); //返回一个常量STL风格的迭代器,该迭代器指向散列中最后一项的下一个指针(不可访问)
    it = hash.erase(it); //从散列中删除与(实参)迭代器pos关联的(键、值)对,并将迭代器返回到散列中的下一项。
    it = hash.find("seven");//,该迭代器指向散列中包含键的项。如果哈希不包含带键的项,则函数返回end()。

     //QHash::const_iterator QHash::begin() const
     //QHash::const_iterator QHash::end() const
     //QHash::const_iterator QHash::find(const Key &key) const
   QHash<QString, int>::const_iterator constIt = hash.cbegin();//返回指向散列中第一项的常量STL样式迭代器。
   qDebug()<<constIt.key();
   constIt = hash.cend(); //返回一个常量STL风格的迭代器,该迭代器指向散列中最后一项的下一个指针(不可访问)
   constIt = hash.constBegin(); //返回指向散列中第一项的常量STL样式迭代器。
   constIt = hash.constEnd(); //返回一个常量STL风格的迭代器,该迭代器指向散列中最后一项的下一个指针(不可访问)
    constIt = hash.constFind("seven"); //返回散列中包含键的项的子hash迭代器。没有这个键则返回 constEnd()
    hash.insert("eight",8); //插入新数据 如果已存在键值 则覆盖原值
    hash.insertMulti("eight",9); //使用键和value值插入新项。如果散列中已经有一个具有相同密钥的项,则此函数将简单地创建一个新项。

    QHash<QString, int>::const_key_value_iterator  ckvit = hash.constKeyValueBegin();//返回指向散列中第一个条目的常量STL样式迭代器。
    ckvit = hash.constKeyValueEnd(); //返回一个常量STL风格的迭代器,该迭代器指向散列中最后一项的下一个指针(不可访问)
    //QHash::const_key_value_iterator QHash::keyValueBegin() const
    //QHash::const_key_value_iterator QHash::keyValueEnd() const

    QPair<QHash<QString, int>::iterator, QHash<QString, int>::iterator> pair = hash.equal_range("seven");
    qDebug()<<"pair="<<pair.first.key()<<pair.first.value();qDebug()<<(--pair.second).key()<<(--pair.second).value();
        //返回一对迭代器,这些迭代器限定了存储在key下的值[first,second]的范围。如果该范围为空,则两个迭代器都将等于end()。
    //QPair<QHash::const_iterator, QHash::const_iterator> QHash::equal_range(const Key &key) const



     QHash<QString, int>::key_iterator keyit = hash.keyBegin(); //返回指向散列中第一个键的常量STL样式迭代器。
     keyit = hash.keyEnd(); //返回一个常量STL风格的迭代器,该迭代器指向散列中最后一项的下一个指针(不可访问)

     QHash<QString, int>::key_value_iterator  kvit = hash.keyValueBegin();//返回指向散列中第一个条目的STL样式迭代器。
     kvit = hash.keyValueEnd(); //返回一个常量STL风格的迭代器,该迭代器指向散列中最后一项的下一个指针(不可访问)


}

MainWindow::~MainWindow()
{
    delete ui;
}


<think>好的,用户现在想了解Qt中的qHash函数。我需要先回忆一下qHash的相关知识。qHashQt中用于为类型生成哈希值的函数,常用于QHash、QSet等容器。用户可能在使用这些容器时遇到了问题,或者需要自定义类型的哈希实现。 首先,我需要解释qHash的基本作用,比如它是如何支持哈希表的,返回类型是uint。然后,可能需要介绍Qt内置支持的类型的qHash,比如基本类型、QString、QByteArray等,用户可能想知道哪些类型可以直接使用而无需自己实现。 接下来,用户可能需要自定义类型的哈希函数,所以需要给出自定义qHash方法,包括全局函数和成员函数两种方式。这里要强调必须将qHash放在同一个命名空间里,尤其是使用ADL查找的情况。可能需要示例代码来说明如何正确实现,比如一个简单的Person类,包含姓名和年龄,然后展示如何为它编写qHash函数。 另外,用户可能关心性能优化的问题,比如如何高效组合多个字段的哈希值。这里需要提到使用位运算或者QtqHashBits、qHashRange等函数。同时,需要注意哈希冲突的问题,虽然无法完全避免,但可以通过合理设计减少冲突。 用户可能还会问到qHash的注意事项,比如一致性(如果两个对象相等,它们的哈希值必须相同),以及何时需要自定义qHash,比如当类型包含指针或动态分配的内存时,可能需要自定义哈希逻辑。 可能用户在使用QHash或QSet时遇到了错误,提示没有合适的qHash函数,这时候需要检查是否为目标类型正确实现了qHash,并且是否在正确的命名空间中。此外,需要提醒用户确保哈希函数的性能,避免过于复杂的计算影响程序效率。 最后,总结qHash的重要性,强调在自定义类型时正确实现qHash的必要性,以及如何利用Qt提供的工具函数来简化实现过程。同时,可能建议用户在遇到性能问题时,考虑哈希函数的质量和效率。</think>以下是对Qt框架中`qHash`函数的逐步解析: ### 1. 核心作用 `qHash`是Qt框架中用于生成哈希值的核心函数,公式表达其基本行为: $$ \text{哈希值} = qHash(key, seed) $$ - 关键应用场景:`QHash`, `QSet`等哈希容器的底层实现 - 返回类型:`uint`(32位无符号整数) ### 2. 内置支持类型 Qt已为常见类型提供默认实现: ```cpp // 基本类型 qHash(bool) qHash(int) qHash(double) // Qt核心类型 qHash(const QString&) qHash(const QByteArray&) qHash(QLatin1StringView) ``` ### 3. 自定义类型实现 #### 方法一:全局函数(推荐) ```cpp namespace MyNamespace { class Person { public: QString name; int age; }; uint qHash(const Person &p, uint seed = 0) noexcept { // 组合成员哈希值 return qHashMulti(seed, p.name, p.age); } } ``` #### 方法二:成员函数(需配合ADL) ```cpp class Book { public: uint hash(uint seed) const noexcept { return qHash(title) ^ qHash(isbn); } private: QString title; QString isbn; }; uint qHash(const Book &b, uint seed = 0) noexcept { return b.hash(seed); } ``` ### 4. 关键规则 1. **一致性要求**: $$ a == b \Rightarrow qHash(a) == qHash(b) $$ 2. **冲突率**:应尽量降低同对象产生相同哈希值的概率 3. **性能要求**:计算速度直接影响哈希容器操作效率 ### 5. 高级工具函数 #### 组合多个字段 ```cpp // 顺序敏感的组合方式 qHashMulti(seed, field1, field2...) // 顺序敏感的组合方式 qHashMultiCommutative(seed, field1, field2...) ``` #### 内存块哈希 ```cpp qHashBits(const void *p, size_t len, uint seed = 0) ``` #### 范围哈希 ```cpp qHashRange(begin_iterator, end_iterator, seed = 0) ``` ### 6. 典型示例 ```cpp struct GeoCoordinate { double latitude; double longitude; int altitude; }; uint qHash(const GeoCoordinate &c, uint seed = 0) noexcept { // 使用Qt提供的组合函数(顺序敏感) return qHashMulti(seed, qHash(c.latitude), qHash(c.longitude), c.altitude); } // 使用示例 QSet<GeoCoordinate> locationSet; locationSet.insert({39.9042, 116.4074, 43}); ``` ### 7. 性能优化技巧 1. **预处理关键字段**:对字符串等复杂类型预先计算哈希 2. **避免碰撞热点**:对枚举类等小范围值添加随机种子 ```cpp qHash(enumValue) ^ qHash(seed) ``` 3. **利用缓存**:对变对象可缓存哈希值 ### 8. 调试建议 当出现`no matching function for call to 'qHash'`错误时: 1. 确认函数签名正确 2. 检查是否在相同命名空间 3. 验证是否包含必要头文件 4. 确保没有歧义的重载 ### 9. 版本变化 | Qt版本 | 重要变化 | |--------|----------| | 5.0 | 引入`seed`参数 | | 6.0 | 强制`noexcept`修饰 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值