2013-04-02 23 views
16

请检查该斯卡拉追加到一个可变的LinkedList

import scala.collection.mutable.LinkedList 

var l = new LinkedList[String] 

l append LinkedList("abc", "asd") 

println(l) 
// prints 
// LinkedList() 

import scala.collection.mutable.LinkedList 

var l = new LinkedList[String] 

l = LinkedList("x") 
l append LinkedList("abc", "asd") 

println(l) 
// prints 
// LinkedList(x, abc, asd) 

为什么第二个代码片段的作品,但第一个犯规?这是斯卡拉2.10

回答

20

该文档说If this is empty then it does nothing and returns that. Otherwise, appends that to this.。那正是你观察到的。如果你真的需要一个可变的名单,我会建议你使用scala.collection.mutable.ListBuffer相反,有了它,你可以做

val lb = new ListBuffer[Int] 

scala> lb += 1 
res14: lb.type = ListBuffer(1) 

scala> lb 
res15: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1) 

scala> lb ++= Seq(1,2,3) 
res17: lb.type = ListBuffer(1, 1, 2, 3, 1, 2, 3) 

scala> lb 
res18: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 1, 2, 3, 1, 2, 3) 
+2

但为什么会有这种行为?为什么不追加到自己,而不考虑元素的数量?这不是从'可变'集合中预期的吗? – weima

+0

很嗨,我不知道。如果你想知道确切的原因,你应该尝试官方scala邮件列表。 – drexin

+0

我的猜测是,这是因为它比实际修改列表便宜得多。虽然,恕我直言,打破了隐含的合同,突变操作实际上会改变名单。 – dOxxx

3

据我了解它在列表中(与第一/最后(Nil)元素,如果列表空Nil是第一个也是最后一个元素)。

LinkedList(still)follow“primitive charm”strategy。因此,它不会尝试在Nil之后/之后添加/追加新数据,以获得如下可能的结果:{Nil,newElement}。 (所有Nil后应该是最后一个元素)

当然,它可以检查if列表为空,然后把addingList的开头和Nil到最后。但我猜,这会太“聪明”了。

但是,不管怎样append()回报“期待”的结果就像这样:

val addingList = new LinkedList[String]("a", "b") 
val result = emptyList append addingList 

result = {"a", "b"}.在这种情况下,它会返回“addingList”本身,和/但不改变最初的名单。

如果我们试图为newElement分配给next裁判:

emptyList.next = LinkedList("whatever") 

至于结果,我们将不得不改变emtyList这样的:

LinkedList(null, whatever) 

它将第一个元素创建为null,因为我们已经使用next()为其分配新/下一个元素。所以它移动到最后,因为第一个元素为null,接下来引用我们添加的新元素(addingElelement)。

因为

“的‘的emptyList’也是‘头’链接”

和头部在我们这里头Nil,但Nill不能有未来,所以它必须用next引用新的addingElelement创建新的第一个元素(它具有空值)。

就我个人而言,我觉得它“太原始了”,而不是“那么高雅”。但我想,这取决于。

面向任务的故事:

对于我的首要任务(为什么我开始思考这个“奇怪”列表行为[即使它是可变的) - 我想利用可变列表的一类/对象所谓的Dictionary这将保持Words在它(字典默认没有任何单词)。而且我会有像ddWord(wod:String)这样的方法来添加新单词。现在我的实现将改变(我不打算使用这个LinkedList,而是MutableList这似乎是多个可变比前一个。):

object Dictionary { 

    val words = new mutable.MutableList[Word](); 

    def addWord(word: Word): Unit = { 
    words += word; 
    } 

} 

但可能的实现可能是这样的:

object Dictionary { 

    var words = new mutable.LinkedList[Word](); 

    def addWord(word: Word): Unit = { 

    if (words.isEmpty) { 
     words = words append(mutable.LinkedList[Word](word)) // rely on append result 
    } else { 
     words append(mutable.LinkedList[Word](word)) 
    } 

    } 

} 

但后来我不得不使用var代替val,我应该改变每一个新的Word LinkedList,我的逻辑变得更加复杂。