我正在尝试为链表实现迭代。但是这个实现会抛出堆栈溢出错误。我在这里做错了什么?
即使在我调用类上的任何函数之前,可迭代实现也会抛出错误。
我最初想过,可能是因为对nodeValue和tailList使用了def而不是val。但那并没有解决问题。
我试图将迭代器更改为遍历Int而不是LinkedList。我仍然得到同样的错误。 在此先感谢!!
trait LinkedList extends Iterable[LinkedList]{
def nodeValue: Int
def tailList: LinkedList
}
class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList {
override def iterator: Iterator[LinkedList] = Iterator
.iterate(this: LinkedList)(_.tailList)
.takeWhile(_ != Nil)
}
object Nil extends LinkedList {
def nodeValue= throw new IllegalAccessException("head of Nil")
def tailList = throw new IllegalAccessException("tail of Nil")
override def iterator: Iterator[LinkedList] = Iterator.empty
}
val singleLinkedList = new Node(1,Nil)
val chainedLinkedList = new Node(2,singleLinkedList)
//Printing this first Time
//chainedLinkedList.foreach(println)
输出:
java.lang.StackOverflowError
at scala.collection.AbstractIterable.<init>(LinkedListIterable.sc:50)
at scala.collection.AbstractSeq.<init>(LinkedListIterable.sc:37)
at scala.collection.mutable.AbstractSeq.<init>(LinkedListIterable.sc:44)
at scala.collection.mutable.StringBuilder.<init>(LinkedListIterable.sc:28)
at scala.collection.mutable.StringBuilder.<init>(LinkedListIterable.sc:45)
at scala.collection.mutable.StringBuilder.<init>(LinkedListIterable.sc:50)
at scala.collection.TraversableOnce.mkString(LinkedListIterable.sc:319)
at scala.collection.TraversableOnce.mkString$(LinkedListIterable.sc:318)
at #worksheet#.Node.mkString(LinkedListIterable.sc:6)
at scala.collection.TraversableLike.toString(LinkedListIterable.sc:596)
at scala.collection.TraversableLike.toString$(LinkedListIterable.sc:596)
at #worksheet#.Node.toString(LinkedListIterable.sc:6)
at java.lang.String.valueOf(LinkedListIterable.sc:2990)
at scala.collection.mutable.StringBuilder.append(LinkedListIterable.sc:196)
at scala.collection.TraversableOnce.$anonfun$addString$1(LinkedListIterable.sc:355)
at scala.collection.Iterator.foreach(LinkedListIterable.sc:925)
at scala.collection.Iterator.foreach$(LinkedListIterable.sc:925)
at scala.collection.AbstractIterator.foreach(LinkedListIterable.sc:1413)
at scala.collection.IterableLike.foreach(LinkedListIterable.sc:67)
at scala.collection.IterableLike.foreach$(LinkedListIterable.sc:66)
at #worksheet#.Node.foreach(LinkedListIterable.sc:6)
at scala.collection.TraversableOnce.addString(LinkedListIterable.sc:353)
at scala.collection.TraversableOnce.addString$(LinkedListIterable.sc:349)
at #worksheet#.Node.addString(LinkedListIterable.sc:6)
at scala.collection.TraversableOnce.mkString(LinkedListIterable.sc:319)
at scala.collection.TraversableOnce.mkString$(LinkedListIterable.sc:318)
at #worksheet#.Node.mkString(LinkedListIterable.sc:6)
at scala.collection.TraversableLike.toString(LinkedListIterable.sc:596)
at scala.collection.TraversableLike.toString$(LinkedListIterable.sc:596)
at #worksheet#.Node.toString(LinkedListIterable.sc:6)
at java.lang.String.valueOf(LinkedListIterable.sc:2990)
at scala.collection.mutable.StringBuilder.append(LinkedListIterable.sc:196)
at scala.collection.TraversableOnce.$anonfun$addString$1(LinkedListIterable.sc:355)
at scala.collection.Iterator.foreach(LinkedListIterable.sc:925)
Output exceeds cutoff limit.
更新
问题是由@Dima,Iterator提到的,在容器中迭代一些值而不是容器本身。一旦清楚,我修改了代码,运行正常如下。
trait LinkedList extends Iterable[Int]{
val nodeValue: Int
val tailList: LinkedList
override def toString(): String = this.mkString(" -> ")
}
class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList {
override def iterator: Iterator[Int] = Iterator
.iterate(this: LinkedList)(_.tailList)
.takeWhile(_ != Nil)
.map(_.nodeValue)
}
object Nil extends LinkedList {
lazy val nodeValue= throw new IllegalAccessException("head of Nil")
lazy val tailList = throw new IllegalAccessException("tail of Nil")
override def iterator: Iterator[Int] = Iterator.empty
}
val singleLinkedList = new Node(1,Nil)
val chainedLinkedList = new Node(2,singleLinkedList)
//Printing this first Time
chainedLinkedList.foreach(println)
答案 0 :(得分:3)
嗯,问题是,通常Iterable.iterator
会迭代容器中的值,而不是实际的容器节点。
这里发生的是,当您在REPL中键入new Node(1, Nil)
时,它会尝试打印出结果,并调用Node.toString
,Iterable
在iterator
上实现以遍历整个容器,并将所有值转换为字符串。
因此,它会调用您的next
,获取iterator
(它认为是什么)元素,并尝试将其转换为String。但是,toString
返回的内容不是存储在节点中的值,而是节点本身,因此,当调用Iterable.toString
时,它仍然是相同的iterator
,最终调用相同的{{1}},它将返回相同的节点,它将尝试转换为字符串...等无限递归。