What is the difference between `##` and `hashCode`?

前端 未结 4 1203
陌清茗
陌清茗 2020-11-30 04:53

What is the difference between methods ## and hashCode?

They seem to be outputting the same values no matter which class or hashCode

相关标签:
4条回答
  • 2020-11-30 05:00

    Just want to add to the answers of other posters that although the ## method strives to keep the contract between equality and hash codes, it is apparently not good enough in some cases, like when you are comparing doubles and longs (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)
    
    0 讨论(0)
  • 2020-11-30 05:03

    ## was introduced because hashCode is not consistent with the == operator in Scala. If a == b then a.## == b.## regardless of the type of a and b (if custom hashCode implementations are correct). The same is not true for hashCode as can be seen in the examples given by other posters.

    0 讨论(0)
  • 2020-11-30 05:18

    "Subclasses" of AnyVal do not behave properly from a hashing perspective:

    scala> 1.0.hashCode
    res14: Int = 1072693248
    

    Of course this is boxed to a call to:

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

    We might prefer it to be:

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

    We should expect this given that the int 1 is also the double 1. Of course this issue does not arise in Java. Without it, we'd have this problem:

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

    Luckily:

    scala> Set(1.0) contains 1
    res21: Boolean = true
    
    0 讨论(0)
  • 2020-11-30 05:27

    In addition to what everyone else said, I'd like to say that ## is null-safe, because null.## returns 0 whereas null.hashCode throws NullPointerException.

    From scaladoc:

    Equivalent to x.hashCode except for boxed numeric types and null. For numerics, it returns a hash value which is consistent with value equality: if two value type instances compare as true, then ## will produce the same hash value for each of them. For null returns a hashcode where null.hashCode throws a NullPointerException.

    0 讨论(0)
提交回复
热议问题