【问题标题】:scala append to a mutable LinkedListscala 附加到可变的 LinkedList
【发布时间】:2013-03-23 14:23:29
【问题描述】:

请检查一下

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)

为什么第二个代码 sn-p 有效,而第一个无效?这是在 Scala 2.10 上

【问题讨论】:

    标签: scala collections mutable


    【解决方案1】:

    文档说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)
    

    【讨论】:

    • 但为什么会出现这种行为?为什么不附加到 self 而不管元素的数量?这不是 mutable 集合所期望的吗?
    • 老实说我不知道​​。如果你想知道确切的原因,你应该试试scala官方邮件列表。
    • 我的猜测是因为它比实际修改列表便宜得多。虽然,恕我直言,这违反了突变操作实际上会改变列表的隐含合同。
    • new LinkedList[String]LinkedList[String]() 不一样不是吗?
    【解决方案2】:

    据我了解,它与列表中的第一个/最后一个 (Nil) 元素有关(如果列表为空,Nil 同时是第一个和最后一个元素)。

    LinkedList(仍然)遵循“primitive charm”策略。所以它不会尝试在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 ref:

       emptyList.next = LinkedList("whatever")
    

    结果我们会像这样改变 emtyList:

     LinkedList(null, whatever)
    

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

    因为

    ““emptyList”也是“head”链接”

    在我们的例子中,head 是Nil,但Nill 不能有下一个,所以它必须创建新的第一个元素(它具有空值),next() 引用我们的新addingElelement

    我个人觉得它“太原始”而不是“那么优雅”。但这取决于,我猜。

    以任务为导向的故事:

    对于我的初始任务(为什么我开始考虑这种“奇怪”的列表行为 [即使它是可变的])——我想将可变列表用于名为 Dictionary 的类/对象,这将使 Words 保留在它(字典默认没有任何单词)。我会有像 addWord(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,我的逻辑变得更加复杂。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-17
      • 1970-01-01
      • 1970-01-01
      • 2011-03-28
      • 2021-11-27
      • 2022-01-04
      • 1970-01-01
      • 2012-03-04
      相关资源
      最近更新 更多