【问题标题】:Why is value of a value class as its hashCode "not a good idea"?为什么将值类的值作为其 hashCode “不是一个好主意”?
【发布时间】:2014-11-08 20:05:04
【问题描述】:

Effective Java, 2nd Edn, J. Bloch Item 9 的最后一段 说,对于像IntegerStringDate 等值类, 返回该类的确切值的函数 hashCode 不是一个好主意

因此,类Integer 返回它所代表的整数的value 作为其实例的hashCode 并不是那么好。

StringhashCode() 也不是直接从整体内容(即 String 实例所具有的字符)映射的整数值。

这些hashCode()-s 明显符合合同。

对我来说,这似乎是一个好主意而不是一个坏主意——hashCode-s 会随着对象的值而变化,而这些 hashCodes 在它们被分散到HashMap/HashSet-- 的桶,这样条目的 hashCode-s 不会对条目将进入哪个桶形成偏差。

我在这里缺少什么 - 是什么让将类值直接映射到 hashCode 是一个“坏主意”?

TIA

//============================

编辑

请参阅 Steve Siebert 对此的回答下的 cmets。

【问题讨论】:

    标签: java hash hashmap hashcode


    【解决方案1】:

    它的意思是那些 javadoc 规范准确地说明了 hashCode 是如何创建的。通过这样做,应用程序现在可以始终依赖于这一点......现在这些实现永远不会改变 hashCode 的生成方式。

    这并不意味着你不应该从你的值中派生你的哈希值......只是不要告诉人们你是如何在你的规范中做到这一点的 =)

    【讨论】:

    • 同意这一点。但对此的解决方案应该是强制一个原则“hashCode 不能用作value 的指标/功能替代品”,而不是介于valuehashCode() 之间的良好关系和因此在equals()hashCode() 之间。
    • 我完全同意你的观点,hashCode 在实践中可以被视为返回对象实际值的“不太智能/有损”表示 - 容易受到生日悖论的影响。但是,实际上,哈希不需要 need 与 value 建立关系...hashCode 需要始终为同一个对象返回相同的 int 值(但是这是由您定义的)所以可以在预期的存储桶中找到对象。通常这是通过散列对象的一个​​/多个值来完成的……这是有道理的。但是,如果可以做到,比如说……魔法……那我该评判谁? =)
    • 紧贴hashCodevalue 可能会确保“如果两个对象不相等,那么它们的hashCodes 也不相等”,这对于跨哈希桶均匀分布的条目来说是一件好事 - - 虽然这不是合同的要求。我既没有看到也想不出更好的方法。
    • 哦,我完全同意......但我总是为比我聪明的人保留一个空间,让他们想出更好的东西 =)
    【解决方案2】:

    full quote

    Java平台库中的很多类,如StringInteger, 和 Date, 在他们的规范中包含准确的值 由他们的hashCode 方法作为实例值的函数返回。 这通常不是一个好主意,因为它严重限制了你的能力 在未来的版本中改进散列函数。如果你离开 未指定散列函数的详细信息,发现缺陷或更好 散列函数被发现,您可以更改散列函数 随后的版本,确信没有客户依赖于确切的 哈希函数返回的值。

    强调我的。这本书只是说明在规范中揭示实现细节通常被认为是不好的做法。这使它难以改变。

    它被实现为返回精确值(对于Integer)或某个计算值(对于DateString)这一事实还不错。

    【讨论】:

      【解决方案3】:

      Java API 就是这样做的,它返回整数。

      Integer t = ...;
      t.intValue() == t.hashCode(); // true
      

      我有同样的书在工作。我会在星期一看看。

      如果您真的很担心,请实现 FNV-1a 哈希:

          int hash = 0x4C1DF00D;
          hash = (hash ^ value) * 0x01000193;
      

      【讨论】:

      • 我想知道为什么投反对票?我正计划得出与@SotiriosDelimanolis 相同的结论,但我在别处有这本书,我不知道它可以免费在线获得。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-18
      • 2016-02-01
      • 2020-06-05
      • 1970-01-01
      • 2011-07-25
      • 1970-01-01
      相关资源
      最近更新 更多