Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

hashcode

scala

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 ##.

like image 207
0__ Avatar asked Jan 30 '12 17:01

0__


4 Answers

"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
like image 113
oxbow_lakes Avatar answered Nov 16 '22 09:11

oxbow_lakes


## 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.

like image 23
Jesper Nordenberg Avatar answered Nov 16 '22 08:11

Jesper Nordenberg


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)
like image 6
starling Avatar answered Nov 16 '22 09:11

starling


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.

like image 2
pavel_orekhov Avatar answered Nov 16 '22 08:11

pavel_orekhov