How to get a correct array hashcode in scala?
Asked Answered
C

4

5

What is the suitable way to compute hashCode of an Array that depends on its content?

Array.hashCode is for the array instance:

val h = a.hashCode
println(h == Array(1,2).hashCode) // false

a(0) = 42
println(h == a.hashCode) // true

Note: It'd be better to avoid copying the whole array, to a List for example, prior to computing the hashCode

Why I ask: I use an Array in a class (as a private field) because lookup time is critical, and its content is relevant to compute the hashCode of the class

Cicelycicenia answered 18/11, 2016 at 13:59 Comment(0)
C
5

from https://issues.scala-lang.org/browse/SI-1607, it says that the hashCode of Array is the hashCode from java, as scala Array are java Array. And scala could not changed it.

But it also says that scala has a suitable hashCode method in WrappedArray. Thus:

val a = Array(1,2)
val h = a.toSeq.hashCode // wrapped it in a WrappedArray - no copy
println(h == Array(1,2).toSeq.hashCode) // true

a(0) = 42
println(h == a.toSeq.hashCode) // false
Cicelycicenia answered 18/11, 2016 at 14:5 Comment(0)
G
5

You can also use java.util.Arrays.hashCode(a), it's likely to be faster than a.toSeq.hashCode (since WrappedArray seems to inherit a non-array-specific implementation).

Grade answered 18/11, 2016 at 18:17 Comment(3)
It works well for Array[Int] but I don't know how it does for other (generic) item type. I guess we would need to cast items to object in the more general case, or use some other java functions (?). In the end, I prefer relying on the scala API. But there are maybe drawbacks I am not aware of (efficiency?).Cicelycicenia
WrappedArray probably has a little overhead: it needs a simple class construction (to wrap the array) and each lookup requires an additional function call. But to my experience, it is very difficult to see the difference with direct lookup. I tried and did not manageCicelycicenia
I've made a pull request to ensure this is no longer a concern, and it has been approved github.com/scala/scala/pull/5551.Grade
R
4

You can use the MurmurHash3 algorithm directly.

import scala.util.hashing.MurmurHash3

MurmurHash3.orderedHash(Array(1,2)))
Refraction answered 18/5, 2017 at 13:27 Comment(0)
E
2

Use Arrays.deepHashCode(Object[] a). In scala you should use ugly:

java.util.Arrays.deepHashCode(array.asInstanceOf[Array[Object]])

This method is working for multi-dimension arrays as well

Ethaethan answered 16/12, 2023 at 22:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.