You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Hashable类型存入Set时相等判断未触发,如何修复?

问题解答

为什么自定义相等判断函数未被调用?

Swift中Set基于哈希表实现,元素插入/查找遵循以下逻辑:

  1. 先计算待插入元素的哈希值,定位到对应的哈希桶
  2. 仅当目标哈希桶中已有元素时,才会调用==方法比较元素是否相等

你的NumberPair中,(1,2)和(2,1)的哈希值不同——因为hash(into:)按n1→n2的顺序组合哈希,交换数值顺序后哈希结果必然不同。这两个元素会被分配到不同哈希桶,Set不会触发==方法比较。但根据你的==实现,这两个元素是相等的,违反了Hashable协议的核心规则:所有相等的实例必须拥有完全相同的哈希值。当Set检测到存在相等但哈希值不同的元素时,就会抛出运行时错误。

正确的实现方式

需要调整hash(into:)方法,确保所有逻辑相等的NumberPair实例产生相同哈希值。最简单的方式是基于n1和n2的最小值、最大值组合哈希,消除顺序影响:

struct NumberPair: Hashable {
    let n1: Int
    let n2: Int

    static func == (lhs: NumberPair, rhs: NumberPair) -> Bool {
        (lhs.n1 == rhs.n1 && lhs.n2 == rhs.n2) ||
        (lhs.n2 == rhs.n1 && lhs.n1 == rhs.n2)
    }
    
    func hash(into hasher: inout Hasher) {
        // 用最小值和最大值组合,保证顺序不影响哈希结果
        hasher.combine(min(n1, n2))
        hasher.combine(max(n1, n2))
    }
}

修改后,(1,2)和(2,1)的哈希值完全相同,插入Set时会触发==方法比较,确认二者相等,最终Set中仅保留一个元素,符合预期。

内容的提问来源于stack exchange,提问作者Reinhard Männer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 12:10:49