What is the difference between `##` and `hashCode`?
What is the difference between methods ##
and hashCode
?
They seem to be outputting the same values no matter which class or hashCode
overloading I use. Google doesn't help, either, as it cannot find symbol ##
.
Solution 1:
"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
Solution 2:
##
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.
Solution 3:
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)
Solution 4:
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.