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

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

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)

Ответы на вопрос(2)

Решение Вопроса

data проверка на равенство классов, массивы, как и другие классы, сравниваются с помощью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, Списки сравниваются структурно, поэтому вам не нужно ничего переопределять.

 Chad Mx26 дек. 2017 г., 14:32
Как я могу найти и какой ярлык (если он отличается в IntelliJ) указывает мне на реализацию этого метода?
 Michał Ziobro04 сент. 2018 г., 12:10
Я думаю, что это реализация, но она требует проверки всех свойств
 Zackline03 дек. 2016 г., 12:35
Я не знаю много о Kotlin, но не буду использоватьif(other !is thisClass) return false будь лучше? Тогда вам не понадобится thisClass в следующей строке, потому что компилятор теперь может делать smartcast, верно?
 Marcin Koziński30 мая 2016 г., 13:34
Для получения дополнительной информации о проверке равенства значений массивов в Kotlin смотрите здесь:stackoverflow.com/q/35272761/1402641
 hotkey26 дек. 2017 г., 15:19
@ChadMx, в IntelliJ IDEA, ярлык для создания членовAlt+Insert по умолчанию. Обычно вы можете найти ярлык действия, нажавCtrl+Shift+A и набрав название действия.
 hotkey26 дек. 2017 г., 20:40
@ChadMx, о, я действительно неправильно тебя понял. Так как члены генерируются не как источники Kotlin, а непосредственно как байт-код JVM, возможно только проверить сгенерированный байт-код,Смотри как, Вы найдете сгенерированные методы внутри класса данных.
 mfulton2630 мая 2016 г., 14:01
И если вы не хотите писать собственный метод equals, подумайте об использованииList<Int> вместоIntArray, Это не будет эффективно использовать память, но если вы не создадите очень большие массивы, влияние будет номинальным.
 JGuo14 июн. 2018 г., 00:26
@ hotkey, если у меня есть класс данныхPuzzleBoard(val name: String, val board: IntArray)как мне переопределитьhashCode()?
 Chad Mx26 дек. 2017 г., 20:35
@ hotkey Спасибо, но мне кажется, я не совсем понял. Я имел в виду, как увидеть сгенерированный код для класса данных, если это возможно?

ЗаКлассы данных в 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()))

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

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

println(user.equals(thirdUser))

Он вернет ложь.

Согласно документу метода hashCode ()

open fun hashCode(): Int (source)

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

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

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

Для более подробной информации смотрите это обсуждениеВот

Ваш ответ на вопрос