There's no standard solution; but since HashMap.get(key)
specifies that it compares parameter to stored keys (key.equals(k)
) and not the other way around, you could achieve the desired result with this nasty hack (nasty because it breaks the equals
contract):
class HasHash(private val hash: Int) {
override fun hashCode() = hash
override fun equals(other: Any?) = other != null && other.hashCode() == hash
}
But even then HashSet
on JVM doesn't expose the details you need (like getElement
in Kotlin/Native), so the only solution I can come up with is
val set: HashSet<T> = ...
val map: Map<Any, T> = set.associateBy { it }
fun findByHashCode(hash: Int): T? = map[HasHash(hash)]
which needs to iterate over the set
to construct map
, but only once, so it can still be useful if you need to find many elements in a single set.
In Kotlin/Native it's just
fun <T> HashSet<T>.findByHashCode(hash: Int): T? = getElement(HasHash(hash))
Also if there are multiple elements with the desired hashcode in the set you'll just get one of them.
So you are mapping each item with itself as key? Does it mean that associateby{} automatically takes the hashcode() of the element as key
No. The idea is:
Say set
contains "a"
(hashcode 1
; not really but assume so for this example), "b"
(hashcode 1
), and "c"
(hashcode 2
).
Then map
is "a": "a", "b": "b", "c": "c"
.
Call findByHashCode(1) = map[HasHash(1)]
.
Hashcode of HasHash(1)
is 1
, so it looks up the slot containing keys "a"
and "b"
(let's say in that order). HasHash(1).equals("a")
returns true
, so the value stored with key "a"
is returned and that's "a"
.
or getElement() function automatically checks according to the hashcode of the input element?
What it says is
Return the element from the set equal to element, or null if no such element found.
so it should return "a"
if it compares them in order HasHash(1).equals("a")
.