【问题标题】:Hashcode returning same values for different references [duplicate]哈希码为不同的引用返回相同的值[重复]
【发布时间】:2016-01-29 22:39:02
【问题描述】:

我在想哈希码只在 HashMap、Hashtable 中实现。据我了解,hashCode 值在对象级别上也是相同的。 因此

        String str="Niks";
        String str1=new String("Niks");
        System.out.println(str.hashCode());
        System.out.println(str1.hashCode());

返回相同的代码是因为在对象级别上,哈希码将按如下方式实现。如果我错了,请纠正我。

 result = prime * result + ((str == null) ? 0 : str.hashCode()); 
 result2 = prime * result + ((str1 == null) ? 0 : str1.hashCode()); 

输出:

75268767 75268767

【问题讨论】:

  • 我认为您误解了平等和身份之间的区别,并且哈希码仅与平等有关。
  • @wero:我认为建议的重复问题不适用。提议的副本描述了如何允许重复的哈希码值,而我认为 OP 没有得到基于值的相等性。

标签: java


【解决方案1】:

一般来说,如果我在 hashmap 中使用字符串作为键,我不想担心我用作查找键的字符串是否与我可能插入的引用完全相同以前,这会使事情变得非常复杂。我希望能够创建一个字符串作为键,并且知道,如果地图有一个与我正在使用的值相同的字符串,则地图会找到它。所以比较引用不是我想要的,我想按值比较。

对于像字符串或数字这样的对象(java.lang.Integer、java.math.BigInteger、java.math.BigDecimal),通常比较引用没有用;所有的人都感兴趣的是价值。这些被称为值对象,相等和 hashCode 严格基于对象的值,而不是比较引用。

来自definition posted by Martin Fowler

在 EAA 的 P 中,我将值对象描述为一个小对象,例如货币或日期范围对象。它们的关键特性是它们遵循值语义而不是引用语义。

您通常可以告诉他们,因为他们的相等概念不是基于身份,而是如果它们的所有字段都相等,则两个值对象相等。尽管所有字段都相等,但如果子集是唯一的,则无需比较所有字段 - 例如货币对象的货币代码足以测试相等性。

一般启发式是值对象应该是完全不可变的。如果你想改变一个值对象,你应该用一个新的对象替换这个对象,并且不允许更新值对象本身的值——可更新的值对象会导致别名问题。

【讨论】:

  • 我没有使用 hashmap,当考虑值时,考虑到 str1 与 str 有很大不同。 str1 发生的事情与 str 不同。但是为什么两者都返回相同的哈希码。我得到的哈希码从不依赖于引用,但是为什么当它们都不同时字符串返回相同的哈希码。你能告诉我忽略哈希图吗
  • @niks:哪两个字符串不同?看来您的问题需要一个更好的例子。
  • 我认为 str 和 str1 是不同的对象。但是现在我很清楚,由于对象值是相同的,当从 equals 方法中看到时,它们将返回相同的哈希码,这就是我的示例所发生的情况
  • 那么哈希码不仅用于hashmap中的桶,还用于堆中的所有对象?
  • @niks:我不清楚你在问什么。 java.lang.Object 实现了哈希码,因此 jvm 中的每个对象都有一个。
【解决方案2】:

对象的hashCode() 方法用于将对象插入到HashTable、HashMap 或HashSet 中。同样重要的是equals() 方法。

如果两个对象是equal,就像您在示例中演示的那样(两个值为“Niks”的字符串)(有关更多信息,请参阅this answer),那么它们将具有相同的哈希,这是需要注意的重要一点是不是因为两个Object有相同的hash,所以它们可能不相等!

【讨论】:

    猜你喜欢
    • 2013-02-08
    • 2018-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-13
    • 1970-01-01
    • 2019-10-30
    • 2015-09-08
    相关资源
    最近更新 更多