Метод равенства для класса данных в котлине

У меня есть следующий класс данных

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

Я прочитал, что классы данных в Kotlin получают бесплатный метод equals () / hashcode ().

Я создал два объекта.

 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)) 

Но все же следующие утверждения возвращают false.

 board1 == board2 board1.equals(board2) 

    В тестах классов data Kotlin проверка равенства, массивы, как и другие классы, сравниваются с помощью equals(...) , который сравнивает ссылки массивов, а не контент. Такое поведение описано здесь :

    Итак, всякий раз, когда вы говорите

    • arr1 == arr2

    • DataClass(arr1) == DataClass(arr2)

    вы получаете массивы, сравниваемые по equals() , т.е. по ссылке.

    При условии,

     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 

    Чтобы переопределить это и массивы сравнены структурно, вы можете реализовать equals(...) + hashCode() в своем классе данных, используя Arrays.equals(...) и 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) } 

    Этот код – это то, что IntelliJ IDEA может автоматически генерировать для не-данных классов.

    Другое решение – использовать List<Int> вместо IntArray . Сравнение списков структурно, так что вам не нужно переопределять что-либо.

    Для классов данных в Kotlin метод hashcode () будет генерировать и возвращать одно и то же целое число, если значения параметров одинаковы для обоих объектов.

     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())) 

    Запуск этого кода вернет True и False, поскольку, когда мы создали объект secondUser, мы передали тот же аргумент, что и пользователь объекта, поэтому целое число hashCode (), сгенерированное для обоих из них, будет таким же.

    также если вы проверите это:

     println(user.equals(thirdUser)) 

    Он вернет false.

    В соответствии с методом hashCode ()

     open fun hashCode(): Int (source) 

    Возвращает значение хэш-кода для объекта. Общий контракт hashCode:

    Всякий раз, когда он вызывается одним и тем же объектом более одного раза, метод hashCode должен последовательно возвращать одно и то же целое число, при условии, что информация, используемая при равных сравнениях с объектом, не изменяется.

    Если два объекта равны в соответствии с методом equals (), то вызов метода hashCode для каждого из двух объектов должен давать одинаковый целочисленный результат.

    Подробнее см. Здесь здесь.