Yes, java has Objects.hash(...)
, but I’ve always hated that it allocates a new array and boxes all the parameters. There should really be a simple Kotlin alternative that doesn’t have all that overhead.
If you have fields a
, b
, c
, d
, and e
, what’s the best way to combine their hashes in kotlin?
This works:
fun hashCode() =
(((a.hashCode()*31 + b.hashCode)*31 + c.hashCode())*31 + d.hashCode())*31 + e.hashCode()`
… but who wants to count all those brackets?
I’m currently doing this:
fun hashCode() = a.hashCode()
.times(31).plus(b.hashCode())
.times(31).plus(c.hashCode())
.times(31).plus(d.hashCode())
.times(31).plus(e.hashCode())
That’s pretty fun.
Does anyone have a better way?
1 Like
At this moment I don’t think that there is any better solution than yours Although a potential approach would be to use an inline function:
inline fun hashCodeOf(a: Any?, b: Any?, c: Any?): Int = a.hashCode()
.times(31).plus(b.hashCode())
.times(31).plus(c.hashCode())
private class MyDataClass(val a: Int, val b: Long, val c: Double) {
override fun hashCode() = hashCodeOf(a, b, c)
override fun equals(other: Any?) = this === other || other is MyDataClass
&& a == other.a
&& b == other.b
&& c.compareTo(other.c) == 0
}
Unfortunatelly, even after inlining a boxing issue still remains. This could probably be optimized if an official ticket was posted
An improvement on the above:
inline fun hashAll(vararg vals: Any?): Int {
var res = 0
for (v in vals) {
res += v.hashCode()
res *= 31
}
return res
}
IIUC this will not create any intermediate array, because of the inlining.
It does create an array even if it is inlined, it has the same problem as Objects.hash(...)
2 Likes
Forgive me if I’m pointing out the obvious, but are you aware that a kotlin data class creates equals, hashCode, and toString for you?
Also, if I’m creating a hashcode function for something other than a data class that needs it, I usually go for speed (and less prone to manual mistakes) over beauty, so I personally prefer alt + insert generate “equals() and hashCode()”
1 Like
Yeap, data classe are a big beauty, but there are situations, like inheritance, where it simply won’t work with data classes alone.
2 Likes