消除Scala堆栈实现中的空值使用

时间:2015-07-12 20:29:52

标签: scala

我正在学习Scala并且正在将一些Stack实现作为练习。我做了这个并且有一些明显的问题。

class LinkedStack[T] extends Stack[T] {
  var current: Node = null
  var n: Int = 0

  private class Node(e: T, prev: Node) {
    val element: T = e
    var previous: Node = prev
  }

  override def pop(): T = {
    if (n == 0) {
      throw new NoSuchElementException
    }
    val popNode: Node = current
    current = current.previous
    popNode.previous = null
    n -= 1

    popNode.element
  }

  override def peek(): T = {
    if (n == 0) {
      throw new NoSuchElementException
    }

    current.element
  }

  override def push(element: T): Unit = {
    if (element == null) {
      throw new NullPointerException
    }
    val newNode: Node = new Node(element, current)
    current = newNode

    n += 1
  }

  override def size(): Int = {
    n
  }

  override def toString(): String = {
    val builder = new StringBuilder("Stack top [")
    var temp: Node = current

    if (n == 0) {
      builder.append("]")
      return builder.toString()
    }
    while (temp.previous != null) {
      builder.append(temp.element).append(", ")
      temp = temp.previous
    }

    builder.append(temp.element).append("]")

    builder.toString()
  }
}

该特征包括除toString之外的所有元素。我的主要问题是我非常自由地使用null。我知道在Scala和行

中根本不应该这样做
var current: Node = null

在构造函数中生成编译错误。我应该如何实现构造函数来创建一个空堆栈?什么是null的最佳替代?

修改 您可能已经注意到Node类应该重写为

private class Node(val element: T, var previous: Node) {}

在阅读了Rex Kerr的回答之后,我意识到了这一点。我忘记了当我第一次写这篇文章的时候我在Scala编程。

2 个答案:

答案 0 :(得分:2)

只要那些null永远不会泄漏出来并且逻辑是正确的,那么使用null作为您班级内部成员的一部分非常错误很简单,所以你可以确定。

但如果您不想使用null进行练习,您有两种选择。一种方法是使用内置替代方案:代替Node使用Option[Node]并使用None代替null。鉴于您的列表是不变的,这是更简单的方法。

其次,您可以使用如下层次结构替换Node

trait Node
class Elt(val element: T, val previous: Node) extends Node {}
object End extends Node

然后,您现在在End使用null时使用Node,并在任何需要走路或做某事的时候匹配def peek = current match { case End => throw new NoSuchElementException case Elt(e, _) => e } ,例如

End

当然这意味着每个列表都必须创建一个额外的对象(null),并且存在各种其他缺点,其中大部分都可以在某种程度上得到。但是对于避免 <log4net> <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender"> <file value="C:\LogFiles\Staging_WebAQPro\s_waq_" /> <datePattern value="yyyy-MM-dd'.log'" /> <staticLogFileName value="false" /> <preserveLogFileNameExtension value="true" /> <appendToFile value="true" /> <countDirection value="1" /> <rollingStyle value="Composite" /> <maxSizeRollBackups value="-1" /> <maximumFileSize value="10MB" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="[%d]: %15property{adrs}: %4t: %5p: %m%n" /> </layout> </appender> <root> <level value="DEBUG" /> <appender-ref ref="RollingLogFileAppender" /> </root> </log4net> 的练习,你可以忽略这些并发症。

答案 1 :(得分:0)

我也在scala学习我的堆栈实现,这很简单,我使用了scala可变数组缓冲区

object Stack{
var stack=scala.collection.mutable.ArrayBuffer[Int]()

def isEmpty():Boolean={
  if(stack.length==0) true
  else false
}

def push(input:Int):Unit={
  stack+=input
}

def size():Int={
  stack.length
}

 def pop():Int={
   stack.remove(stack.length-1)
 }

def peek()={
   stack(stack.length-1)
 }

}