【问题标题】:What is the difference between `##` and `hashCode`?`##` 和 `hashCode` 有什么区别?
【发布时间】:2012-01-30 17:35:43
【问题描述】:

方法##hashCode 有什么区别?

无论我使用哪个类或hashCode 重载,它们似乎都在输出相同的值。谷歌也没有帮助,因为它找不到符号##

【问题讨论】:

  • 1.0 hashCode v 1.0 ## v 1 hashCode v 1 ##scala-lang.org/api/current/scala/Any.html
  • 有点离题,但您可以使用 SymbolHound 搜索此类符号。
  • 嗯,好的。所以,1.hashCode==1.##,和1.2.hashCode==1.2.##。唯一表现不同的是1.0.hashCode!=1.0.##(所以##更适合比较数字)。
  • 来自 Scala 文档中的任何“等效于 x.hashCode 除了盒装数字类型。对于数字,它返回与值相等一致的哈希值:如果两个值类型实例比较为真,那么 ## 将为它们中的每一个生成相同的哈希值。”。
  • @om-nom-nom,有点话题,但感谢您的提示。太棒了!

标签: scala hashcode


【解决方案1】:

AnyVal 的“子类”从散列的角度来看不正确

scala> 1.0.hashCode
res14: Int = 1072693248

当然,这是装箱到调用:

scala> new java.lang.Double(1.0).hashCode
res16: Int = 1072693248

我们可能更喜欢这样:

scala> new java.lang.Double(1.0).##
res17: Int = 1

scala> 1.0.##
res15: Int = 1

鉴于int 1 也是double 1,我们应该预料到这一点。当然这个问题在Java 中不会出现。没有它,我们就会遇到这个问题:

Set(1.0) contains 1 //compiles but is false

幸运的是:

scala> Set(1.0) contains 1
res21: Boolean = true

【讨论】:

  • 因此,在为特定类同时实现 equalshashCode 时,我不确定这如何转化为最佳策略。我假设hashCode 实现应该使用##。但是,equals 实现应该使用hashCode 还是##?这是我在另一个线程上提供的答案,假设equals 实现应该使用hashCodehashCode 实现应该使用##。对此的评估和反馈将不胜感激。 stackoverflow.com/a/56509518/501113
【解决方案2】:

## 被引入是因为 hashCode 与 Scala 中的 == 运算符不一致。如果a == ba.## == b.## 不管a 和b 的类型(如果自定义hashCode 实现是正确的)。 hashCode 的情况并非如此,从其他海报给出的示例中可以看出。

【讨论】:

  • 因此,在为特定类同时实现equalshashCode 时,我不确定这如何转化为最佳策略。我假设hashCode 实现应该使用##。但是,equals 实现应该使用hashCode 还是##?这是我在另一个线程上提供的答案,假设equals 实现应该使用hashCodehashCode 实现应该使用##。对此的评估和反馈将不胜感激。 stackoverflow.com/a/56509518/501113
【解决方案3】:

只是想添加到其他海报的答案,虽然## 方法努力保持相等和哈希码之间的合同,但在某些情况下它显然不够好,比如当你比较双精度和长整数时(scala 2.10.2):

> import java.lang._
import java.lang._

> val lng = Integer.MAX_VALUE.toLong + 1
lng: Long = 2147483648

> val dbl = Integer.MAX_VALUE.toDouble + 1
dbl: Double = 2.147483648E9

> lng == dbl
res65: Boolean = true

> lng.## == dbl.##
res66: Boolean = false

> (lng.##, lng.hashCode)
res67: (Int, Int) = (-2147483647,-2147483648)

> (dbl.##, dbl.hashCode)
res68: (Int, Int) = (-2147483648,1105199104)

【讨论】:

  • 真的吗?这是一个错误吗?
  • 这显然是根据 scaladoc for ## "... 它返回一个与值相等一致的哈希值:如果两个值类型实例比较为真,那么 ## 将产生相同他们每个人的哈希值..."
  • 我刚刚在 scala 2.11.7 中检查了这一点,并没有看到 ==.## == .## 的相同行为
【解决方案4】:

除了其他人说的,我想说## 是空安全的,因为null.## 返回0null.hashCode 抛出NullPointerException

来自 scaladoc:

除盒装数字类型和 null 外,等效于 x.hashCode。对于数字,它返回一个与值相等一致的哈希值:如果两个值类型实例比较为真,那么 ## 将为它们中的每一个生成相同的哈希值。对于 null 返回一个哈希码,其中 null.hashCode 抛出一个 NullPointerException。

【讨论】:

    猜你喜欢
    • 2020-03-12
    • 2017-08-05
    • 1970-01-01
    • 2010-10-02
    • 2011-12-12
    • 2010-09-16
    • 2012-03-14
    • 2012-02-06
    • 2011-02-25
    相关资源
    最近更新 更多