Scala: почему мои экземпляры класса дел имеют одинаковый hashCode? - PullRequest
0 голосов
/ 04 июля 2018

Я использую Scala 2.11.

У меня есть класс дел Размер , и я создал 3 экземпляра этого класса. Когда я положил их в HashSet , я неожиданно обнаружил, что только 1 был добавлен правильно. Тогда я попытался отладить и обнаружил, что у них был тот же самый хэш-код.

Я новичок в Scala, но у меня большой опыт работы с Java. Мне интересно, почему все они имеют одинаковый hashCode, даже если у них разные поля, и какова реализация метода hashCode по умолчанию в классе case Scala? И как работает HashSet / HashMap в Scala?

Вот мой пример кода.

object Echo {
  def main( args:Array[String] ):Unit = {
    var d1 = new Dimension
    d1.name = "d1"
    d1.dimensionId = "1"
    println("d1:" + d1.hashCode()) // d1, d2, d3 have the same hashCode

    var d2 = new Dimension
    d2.name = "d2"
    d2.dimensionId = "2"
    println("d2:" + d2.hashCode())

    var d3 = new Dimension
    d3.name = "d3"
    d3.dimensionId = "3"
    println("d3:" + d3.hashCode())

    var l = List(d1, d2, d3)
    val categories = mutable.HashSet.empty[Dimension]

    l.foreach(md => {
      categories += md
    })

    println(categories.size) // size is 1
  }
}

case class Dimension() {
  var dimensionId: String = _
  var name: String = _
}

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Цитирование спецификация :

Каждый класс case неявно переопределяет некоторые определения методов класса scala.AnyRef, если уже не дано определение того же метода в самом случае класса или конкретное определение того же метода дается в некотором базовом классе класса case, отличного от AnyRef. В частности:

  • Метод equals: (Any)Boolean - структурное равенство, где два экземпляры равны, если они оба принадлежат к рассматриваемому классу дел и они имеют равные (по отношению к равным) аргументы конструктора (ограничено элементами класса, то есть первым параметром раздел).

  • Метод hashCode: Int вычисляет хеш-код. Если Методы hashCode элементов структуры данных отображаются равными (по отношению равным) значения равны хеш-кодам, тогда класс case hashCode метод тоже.

Поскольку список аргументов конструктора пуст, каждый Dimension пусто equals любой другой Dimension, поэтому их hashCode также должны быть одинаковыми.

Только не смешивайте классы case с этими странными неинициализированными var s или, по крайней мере, делайте это более осторожно.

0 голосов
/ 04 июля 2018

Как указывалось, hashCode использует первичные аргументы конструктора для генерации своего результата. Вы все еще можете иметь рабочую версию вашего класса case, используя vars, например:

case class Dimension(var dimensionId: String = "", var name: String = "")
0 голосов
/ 04 июля 2018

HashCode в scala рассматривает только атрибуты в конструкторе для классов case.

Если вы определите свой класс дел более функциональным и масштабным способом (например, гарантируя неизменность), поведение будет ожидаемым:

ОПРЕДЕЛЯЮЩИЕ

case class Dimension(dimensionId: String, name: String)
val d1 = Dimension("1", "d1")
val d2 = Dimension("2", "d2")

РЕЗУЛЬТАТ

  scala> println("d1:" + d1.hashCode())
    d1:732406741
    scala> println("d2:" + d2.hashCode())
    d2:952021182

Вы можете найти сгенерированный код для метода хэш-кода в этом удивительном ответе здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...