如何List
在 Scala 2.7.5 中向 a 添加元素,而不创建新元素List
且不使用已弃用的解决方案。
6 回答
您可以使用 a ListBuffer
,它提供恒定时间追加:
val buffer = new scala.collection.mutable.ListBuffer[Int]
buffer += 1
buffer += 2
val list = buffer.toList
值得指出的是,List
在scala中有一个非常具体的含义,并不等同于java.util.List
接口。List
是一个密封的抽象类,表示具有head和tail的递归数据结构。(scala 中确实存在类似 Java 列表的结构,其中一些是可变的。)
Scala 的List
s 是不可变的;不可能以任何方式修改列表,尽管您可以创建一个新列表添加到现有列表之前(这会返回一个新对象)。即使它们是不可变的,该结构在对象创建方面并不比附加到一个java.util.LinkedList
该+
方法已被弃用,因为它效率低下;改为使用:
val newList = theList ::: List(toAppend)
我想另一种方法是在前面加上 2 个反转:
val newList = (toAppend :: theList.reverse).reverse
我怀疑这是否更有效!一般来说,如果我想要追加行为,我会使用prepend然后reverse
(在需要访问列表时):
val newList = toAppend :: theList
//much later! I need to send the list somewhere...
target ! newList.reverse
将元素附加到 Scala 2.7.5 中的列表的非弃用方式?
那不存在,也永远不会存在。
如何在 Scala 2.7.5 中将元素添加到列表中,而不创建新列表且不使用已弃用的解决方案。
使用::
:
val newList = element :: oldList
或者,如果list
是var
,
list ::= element
它不会创建一个新的List
(尽管它会创建一个新的::
,也称为cons),而是向其中添加一个元素。
如果您想在不创建新序列的情况下将元素附加到序列,请使用可变数据结构。
不推荐使用列表上的+=
方法,因为它向尾部添加了一个元素,这很昂贵。将元素添加到列表中最便宜的方法是使用::=
.
因此,弃用警告是一个微妙的提示,您应该重新设计程序以通过预先而不是附加来工作:
scala> var l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> l ::= 4
scala> l
res1: List[Int] = List(4, 1, 2, 3)
(注意::=
and +=
on avar
不是真正的方法,而是糖 forl = l :: elem
等)
或者这个: http ://www.scala-lang.org/docu/files/api/scala/collection/mutable/ListBuffer.html#%2B%3A%28A%29
基本技巧是使用可变列表(或具有类似功能的类)
对于某些操作 List 实现,以下内容不正确。感谢 sschaef 的更正。
我在这里没有提到的一个非常重要的一点是,从另一个集合创建一个新集合在 Scala 中不一定像在 Java 中那样昂贵。这个概念称为持久性。Daniel Spiewak 在他的文章http://www.codecommit.com/blog/scala/scala-collections-for-the-easily-bored-part-1中阐述了这一点。
这是相关部分的片段,
当然,自然会想到的问题是,性能呢?如果每个调用实际上为每个递归调用创建一个全新的 Set,那不是需要大量低效的对象复制和堆操作吗?好吧,事实证明,情况并非如此。是的,每次都必须创建一个新实例,这在 JVM 上是一项相对昂贵的操作,但几乎没有任何内容被复制。Scala 的所有不可变数据结构都有一个称为持久性的属性,这意味着您在创建新容器时不会将数据从旧容器中复制出来,您只需将新容器引用旧容器并将其所有内容视为是它自己的。
因此,虽然使用可变列表会更便宜,但它并不像在 Java 下那样令人担忧。