【发布时间】: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