带有循环引用的scala案例类哈希码

问题描述 投票:0回答:1

正如Scala文档所说,“案例类是按结构而不是按引用进行比较”。

我正在尝试创建一个带有循环的链表,然后将这个循环表中的节点添加到可变集合中。当使用常规类时,它成功了,但是在案例类中,我遇到了堆栈溢出。

我很好奇,为什么Scala在检查结构之前不first检查参考。我的想法是,如果引用相同,则可以保证结构相同,因此这可以是一种快捷方式,也可以使用循环引用。

代码:

object CaseClassHashcodeExample {
  def main(args: Array[String]): Unit = {
    val head = new ListNode(0)
    head.appendToTail(1)
    head.appendToTail(2)
    head.appendToTail(3)
    head.next.next.next = head.next
    val set = collection.mutable.Set[ListNode]()
    set.add(head)
    assert(set(head))
  }
}

case class ListNode(var data: Int, var next: ListNode = null) {
  def appendToTail(d: Int): Unit = {
    val end = new ListNode(d)
    var cur = this
    while (cur.next != null)
      cur = cur.next
    cur.next = end
  }
}
scala hashcode case-class
1个回答
0
投票

我很好奇,为什么Scala在检查结构之前不先检查参考信息

嗯,您想要什么[[确切地检查?当前生成的代码看起来像

def hashCode() = 31 * data.hashCode() + next.hashCode()
您可以尝试的一件事是

def hashCode() = if (next != this) 31 * data.hashCode() + next.hashCode() else ???

但实际上并没有帮助:在您的情况下,不是next等于this,而是next.next

next.hashCode不知道它是从this.hashCode调用的,因此无法将其自己的nextthis进行比较。

您可以创建一个考虑一组“可见”对象的辅助方法:

def hashCode() = hashCode(Nil) def hashCode(seen: List[ListNode]) = if (seen.contains(this)) 0 else 31 * data.hashCode() + next.hashCode(this :: seen)

但是这两者都大大降低了普通情况的速度,并且很难正确解决。
© www.soinside.com 2019 - 2024. All rights reserved.