В чем разница между `##` и `hashCode`?
В чем разница между методами ##
а также hashCode
?
Кажется, они выводят одинаковые значения независимо от того, какой класс или hashCode
перегруз я использую. Google тоже не помогает, так как не может найти символ ##
,
3 ответа
"Подклассы" 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
##
был введен потому что hashCode
не согласуется с ==
оператор в Скала. Если a == b
затем a.## == b.##
независимо от типа А и В (если пользовательский hashCode
реализации правильные). То же самое не верно для hashCode
как видно из примеров, приведенных другими авторами.
Просто хочу добавить к ответам других авторов, что, хотя метод ## стремится сохранить контракт между равенством и хеш-кодами, он, по-видимому, недостаточно хорош в некоторых случаях, например, когда вы сравниваете double и long (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)
В дополнение к тому, что говорили все, я хотел бы сказать, что ##
является нулевым, потому что null.##
возвращается 0
в то время как null.hashCode
бросает NullPointerException
.
Из scaladoc:
Эквивалентен x.hashCode, за исключением упакованных числовых типов и null. Для числовых значений он возвращает хэш-значение, которое согласуется с равенством значений: если два экземпляра типа значения сравниваются как истинные, то ## будет генерировать одинаковое хеш-значение для каждого из них. Для null возвращает хэш-код, где null.hashCode выдает исключение NullPointerException.