Scala中的Java样式LinkedList

时间:2016-10-25 20:37:05

标签: java scala

尝试在Scala中实现LinkedList。我很乐意在scala中创建一个不可变的List作为ADT,如下所示。

sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]

但是在scala中尝试创建一个带有“null”终止的java样式链表似乎很难,因为Scala中有一个空引用。

我尝试了以下

sealed trait Node[+A] 
case object Empty extends Node[Nothing]
case class LinkedList[A](var head: A,var tail: Node[A]) extends Node[A]

LinkedList是一个具有可变成员的案例类,对我来说似乎非常错误。但由于我必须在每次操作之前区分Empty和LinkedList,我需要模式匹配的帮助。

这是正确的方法吗?或者有更好的方法吗?

同样在第二个例子中,我无法拥有像这样的共同变体类型

case class LinkedList[+A](var head: A,var tail: Node[A]) extends Node[A]

1 个答案:

答案 0 :(得分:1)

  

但是由于我必须在每次操作之前区分Empty和LinkedList,我需要模式匹配的帮助。

不,你不应该这样做。向Node添加方法,并在EmptyLinkedList中以不同方式实施。{}当您需要模式匹配时,您可以:

val x: Node[A] = ...
x match {
  case Empty => ...
  case nonEmpty: LinkedList[A] => ... // use nonEmpty

不使LinkedList成为案例类的原因只是它自动允许对链表无意义的操作。

此外,您当前的定义不允许创建空列表,然后向其添加元素(而不是创建新列表)。对于可变链表,列表不能 节点;它应引用到节点。

作为一个起点:

object LinkedList {
  private sealed trait MaybeNode[A] // can't be covariant!
  private case class Empty[A]() extends MaybeNode[A]
  private class Node[A](var value: A, var next: MaybeNode[A])
}
class LinkedList[A] {
  private var first: MaybeNode[A] = Empty()
  def add(x: A): Unit = ???
  def length: Int = ???
  // any other methods you want to support
}

(这是一个单链接的列表,而不是像Java中那样的双重链接列表。)