scala append to a mutable LinkedList
请检查这个
1 2 3 4 5 6 7 8 9
| import scala. collection. mutable. LinkedList
var l = new LinkedList [String ]
l append LinkedList ("abc", "asd")
println (l )
// prints
// LinkedList() |
但是
1 2 3 4 5 6 7 8 9 10
| 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) |
为什么第二个代码片段有效,而第一个无效?这是在 Scala 2.10
上
文档说 If this is empty then it does nothing and returns that. Otherwise, appends that to this.。这正是你观察到的。如果你真的需要一个可变列表,我建议你使用 scala.collection.mutable.ListBuffer 代替,你可以这样做
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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) |
- 但为什么会有这种行为?为什么不附加到 self 而不管元素的数量?这不是 mutable 集合所期望的吗?
-
Hinestly我没有一个想法。如果你想知道确切的原因,你应该试试官方的 scala 邮件列表。
-
我的猜测是因为它比实际修改列表便宜得多。虽然,恕我直言,这打破了突变操作实际上会改变列表的隐含合同。
-
new LinkedList[String] 和 LinkedList[String]() 不一样不是吗?
据我了解,它与列表中的第一个/最后一个 (Nil) 元素有关(如果列表为空 Nil 同时是第一个和最后一个元素)。
LinkedList(仍然)遵循"原始魅力"策略。因此它不会尝试在 Nil 之后添加/追加新数据,从而可能产生如下结果:{Nil, newElement}。 (毕竟 Nil 应该是最后一个元素)
当然可以检查if列表是否为空,然后将addingList放在开头,Nil放在结尾。但这将是"太聪明了",我猜。
但是,无论如何 append() 返回"预期"结果就像这样:
1 2
| val addingList = new LinkedList [String ]("a", "b")
val result = emptyList append addingList |
result = {"a","b"}. 在这种情况下,它会返回 'addingList' 本身,并且/但不会更改初始列表。
如果我们尝试将 newElement 分配给 next ref:
1
| emptyList.next = LinkedList("whatever") |
因此,我们将 emtyList 更改为:
1
| LinkedList (null, whatever ) |
即它将第一个元素创建为 null,因为我们使用 next() 为其分配新/下一个元素。所以它将 Nil 移动到最后,因为第一个为 null 的元素具有对我们添加的新元素 (addingElelement) 的下一个引用。
因为
"the"emptyList" is also the"head" link"
和 head 在我们的例子中 head 是 Nil,但是 Nill 不能有下一个,所以它必须创建新的第一个元素(它具有空值), next() 引用我们的新 addingElelement。
我个人觉得它"太原始"而不是"那么优雅"。但这取决于,我猜。
以任务为导向的故事:
对于我的初始任务(为什么我开始考虑这种"奇怪"的列表行为[即使它是可变的])——我想为一个名为 Dictionary 的类/对象使用可变列表,它会保留 Words它(字典默认没有任何单词)。我会有像 addWord(wod:String) 这样的方法来添加新词。现在我的实现将被更改(我不会使用这个 LinkedList,而是使用 MutableList。它似乎比以前的更易变):
1 2 3 4 5 6 7 8 9
| object Dictionary {
val words = new mutable. MutableList[Word ]();
def addWord (word : Word ): Unit = {
words + = word ;
}
} |
但可能的实现可能是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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,而且我要把每一个新词都转换成LinkedList,我的逻辑变得更复杂了。