アプリ開発備忘録

PlayStationMobile、Android、UWPの開発備忘録

KotlinのMapのKeyについて

MapのKeyって文字列とか数値とかしか使ってなかったけど他のdata classとか使いたいなとなったので調べた。

確かめる

何も考えずdata classを使う

ちゃんと直感的に動く

data class MapKey(val key1: Int, val key2: Int)

fun main(args : Array<String>) {
    // {MapKey(key1=1, key2=0)=0, MapKey(key1=0, key2=0)=1}
    println(mapOf(MapKey(1, 0) to 0, MapKey(0, 0) to 1))

    // {MapKey(key1=0, key2=0)=1}
    println(mapOf(MapKey(0, 0) to 0, MapKey(0, 0) to 1))

equalsで計算しているのかな

違うっぽい

data class MapKey(val key1: Int, val key2: Int) {
    override fun equals(other : Any?) : Boolean {
        return true
    }
}

fun main(args : Array<String>) {
    // {MapKey(key1=1, key2=0)=0, MapKey(key1=0, key2=0)=1}
    println(mapOf(MapKey(1, 0) to 0, MapKey(0, 0) to 1))

    // {MapKey(key1=0, key2=0)=1}
    println(mapOf(MapKey(0, 0) to 0, MapKey(0, 0) to 1))
}

hashでは

違うんか

data class MapKey(val key1: Int, val key2: Int) {
    override fun hashCode(): Int {
        println("hashCode")
        return 0
    }
}

fun main(args : Array<String>) {
    // {MapKey(key1=1, key2=0)=0, MapKey(key1=0, key2=0)=1}
    println(mapOf(MapKey(1, 0) to 0, MapKey(0, 0) to 1))

    // {MapKey(key1=0, key2=0)=1}
    println(mapOf(MapKey(0, 0) to 0, MapKey(0, 0) to 1))
}

両方か

data class MapKey(val key1: Int, val key2: Int) {
    override fun equals(other : Any?) : Boolean {
        println("equals")
        return true
    }

    override fun hashCode(): Int {
        println("hashCode")
        return 0
    }
}

fun main(args: Array<String>) {    
    println(mapOf(MapKey(1, 0) to 0, MapKey(0, 0) to 1))
    
    println(mapOf(MapKey(0, 0) to 0, MapKey(0, 0) to 1))   
}
hashCode
hashCode
equals
{MapKey(key1=1, key2=0)=1}
hashCode
hashCode
equals
{MapKey(key1=0, key2=0)=1}

結論

hashCodeが衝突したらequalsを見ている。

P.S.

確かに毎回equalsを見るよりもhashを見たほうが早い。でも衝突する恐れがあるので衝突した場合はequalsを見るのは納得