Equals method for data class in Kotlin

后端 未结 3 653
半阙折子戏
半阙折子戏 2020-12-24 10:21

I have the following data class

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


        
相关标签:
3条回答
  • 2020-12-24 11:01

    For Data classes in Kotlin, hashcode() method will generate and return the same integer if parameters values are same for both objects.

    val user = User("Alex", 1)
    val secondUser = User("Alex", 1)
    val thirdUser = User("Max", 2)
    
    println(user.hashCode().equals(secondUser.hashCode()))
    println(user.hashCode().equals(thirdUser.hashCode()))
    

    Running this code will return True and False as when we created secondUser object we have passed same argument as object user, so hashCode() integer generated for both of them will be same.

    also if you will check this:

    println(user.equals(thirdUser))
    

    It will return false.

    As per hashCode() method docs

    open fun hashCode(): Int (source)
    

    Returns a hash code value for the object. The general contract of hashCode is:

    Whenever it is invoked on the same object more than once, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.

    If two objects are equal according to the equals() method, then calling the hashCode method on each of the two objects must produce the same integer result.

    For more details see this discussion here

    0 讨论(0)
  • 2020-12-24 11:10

    In Kotlin, equals() behaves differently between List and Array, as you can see from code below:

    val list1 = listOf(1, 2, 3)
    val list2 = listOf(1, 2, 3)
    
    val array1 = arrayOf(1, 2, 3)
    val array2 = arrayOf(1, 2, 3)
    
    //Side note: using a==b is the same as a.equals(b)
    
    val areListsEqual = list1 == list2// true
    val areArraysEqual = array1 == array2// false
    

    List.equals() checks whether the two lists have the same size and contain the same elements in the same order.

    Array.equals() simply does an instance reference check. Since we created two arrays, they point to different objects in memory, thus not considered equal.

    Since Kotlin 1.1, to achieve the same behavior as with List, you can use Array.contentEquals().

    Source: Array.contentEquals() docs ; List.equals() docs

    0 讨论(0)
  • 2020-12-24 11:18

    In Kotlin data classes equality check, arrays, just like other classes, are compared using equals(...), which compares the arrays 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, so that you won't need to override anything.

    0 讨论(0)
提交回复
热议问题