我正在学习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编程。
答案 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)
}
}