UUID的hashValue是非确定性的吗?

ori*_*zil 4 hash uuid deterministic non-deterministic swift

鉴于我认为是相同的 Swift UUID,我hashValue在后续运行代码时得到了不同的 s。在单次运行中它是一致的。

例如:

func UUIDTest() {
    let uuid = UUID(uuidString: "00000000-0000-0000-0000-000000000001")
    
    let h = uuid.hashValue
    
    print("\(String(describing: uuid)) -> \(h)")
    
    /*
     
     Run #1:
     Optional(00000000-0000-0000-0000-000000000001) -> 8072320274727128679

     Run #2:
     Optional(00000000-0000-0000-0000-000000000001) -> -2566074080105686496

     */
}
Run Code Online (Sandbox Code Playgroud)

文档并未明确说明哈希值是否严格属于 UUID 的函数,或者是否还有其他成分。

对于 Hashable 是否有一些我还没有的理解?

Sul*_*han 7

不仅是 UUID,整个 SwiftHashable协议都是不确定的,而且是有意为之的。

来自Hasher文档。

在 Swift 程序的执行过程中,Hasher 保证只要输入完全相同的字节序列,最终确定的程序就始终会产生相同的哈希值。然而,底层哈希算法被设计为表现出雪崩效应:种子或输入字节序列的轻微变化通常会导致生成的哈希值发生巨大变化。

不要在程序执行过程中保存或以其他方式重复使用哈希值。Hasher 通常是随机播种的,这意味着它会在程序的每次新执行时返回不同的值。Hasher 实现的哈希算法本身可能在标准库的任意两个版本之间发生变化。

有多种原因可以解释为什么这是一件好事。安全性就是其中之一(请参阅哈希洪泛攻击)。它还可以防止程序员将哈希值用于其设计目的之外的内容(例如相等比较)。

请参阅SE-0206中的完整原理

  • 有关更多详细信息,hasher 使用在进程启动期间在运行时初始化的内部种子值。种子值通常由随机数生成器产生。因为同一对象的哈希器对于同一执行是唯一的。在下一次执行中,该种子值不同,因此哈希值也会不同。但是可以通过定义值为“1”的“SWIFT_DETERMINISTIC_HASHING”环境变量来禁用此行为 (3认同)