Vaibhav Vaibhav - 6 months ago 93
Android Question

Equals method for data class in kotlin

I have the following data class

data class PuzzleBoard(val board: IntArray) {
val dimension by lazy { Math.sqrt(board.size.toDouble()).toInt() }
}


I read that data classes in Kotlin get equals()/hashcode() method for free.

I instantiated two objects.

val board1 = PuzzleBoard(intArrayOf(1,2,3,4,5,6,7,8,0))
val board2 = PuzzleBoard(intArrayOf(1,2,3,4,5,6,7,8,0))


But still the following statements return false.

board1 == board2
board1.equals(board2)

Answer

Arrays in Kotlin data classes equality check are compared using equals(...), which compares the references, not the content. This behavior is described here:

So, whenever you say

  • arr1 == arr2

  • DataClass(arr1) == DataClass(arr2)

  • ...

you get the arrays compared through equals(), i.e. referentially.

Given that,

val arr1 = intArrayOf(1, 2, 3)
val arr2 = intArrayOf(1, 2, 3)

println(arr1 == arr2) // false is expected here
println(PuzzleBoard(arr1) == PuzzleBoard(arr2)) // false too


To override this and have the arrays compared structurally, you can implement equals(...)+hashCode() in your data class using Arrays.equals(...) and Arrays.hashCode(...):

override fun equals(other: Any?): Boolean{
    if (this === other) return true
    if (other?.javaClass != javaClass) return false

    other as PuzzleBoard

    if (!Arrays.equals(board, other.board)) return false

    return true
}

override fun hashCode(): Int{
    return Arrays.hashCode(board)
}

This code is what IntelliJ IDEA can automatically generate for non-data classes.

Another solution is to use List<Int> instead of IntArray. Lists are compared structurally.

Comments