【问题标题】:How does Set resolve hash collisions?Set 如何解决哈希冲突?
【发布时间】:2017-08-11 07:59:42
【问题描述】:

基于此问题中接受的答案:How does Set ensure equatability in Swift?
hashValue 用于第一个唯一性测试。如果hashValue 匹配另一个元素的hashValue,则== 用作备份测试。

但是,在幕后 Set 必须为每个元素存储一个唯一标识符。考虑这个例子:

struct Country {
    let name: String
    let capital: String
}

extension Country: Hashable {
    static func == (lhs: Country, rhs: Country) -> Bool {
        return lhs.name == rhs.name && lhs.capital == rhs.capital
    }

    var hashValue: Int {
        return name.hashValue ^ capital.hashValue
    }
}

let singapore = Country(name: "Singapore", capital: "Singapore")
let monaco = Country(name: "Monaco", capital: "Monaco")
singapore.hashValue // returns 0
monaco.hashValue // returns 0


var countries: Set<Country> = []
countries.insert(singapore)
countries.insert(monaco)

countries // Contains both singapore and monaco

如您所见,某些国家/地区的名称与其首都名称相同。这将产生hashValue 碰撞。该集合将运行更昂贵的== 以确定它可能不是O(1) 的唯一性。但是在做完这个比较之后,Set 必须为这个元素生成唯一的标识符来存储在幕后。

问题: set 如何为这样的碰撞元素生成唯一标识符?

【问题讨论】:

  • 当您打印单个 String 成员的 hashValues 时会发生什么?
  • 这种情况称为“哈希冲突”。这种情况下的集合,而不是只有一个对象用于该 hashValue,将创建另一个集合,如内部 Set,并将对象存储在那里。
  • 为什么需要生成唯一标识符?哈希冲突是一个已知问题,如果您正在设计自己的符合Hashable 协议的类,您有责任使哈希冲突的概率尽可能小。正如您在问题中已经说明的那样,Swift 具有内置机制,即使存在哈希冲突,也可以检查唯一性,因此无需生成另一个“唯一”标识符...
  • 我确定在幕后 Set 会生成唯一标识符来替换碰撞的 hashValue 我不明白为什么即使我阅读了你的两个原因你也能确定。您需要展示一些稳定的可验证证据,而不是您的感觉或直觉。据我测试,哈希冲突只会增加对== 的调用次数。

标签: swift


【解决方案1】:

似乎hash值只是用来标识用于内部插入元素的bucket(不存储hash),但使用==比较是否使用了元素。如果集合存储增长,还需要重新散列所有元素。

您可以在here 的讨论中获得更多信息。

【讨论】:

  • 谢谢你的链接,会去看看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-05
  • 1970-01-01
  • 2013-09-01
  • 2015-04-07
相关资源
最近更新 更多