在 Scala 2.7.5 中将元素附加到列表的非弃用方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2221914/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 01:55:30  来源:igfitidea点击:

Non deprecated way of appending an element to a List in Scala 2.7.5?

listscaladeprecated

提问by Geo

How do you add an element to a Listin Scala 2.7.5, without creating a new Listand without using a deprecated solution.

如何List在 Scala 2.7.5中将元素添加到 a ,而不创建新的List和不推荐使用的解决方案。

回答by Fabian Steeg

You could use a ListBuffer, which provides constant time append:

您可以使用 a ListBuffer,它提供恒定时间附加:

val buffer = new scala.collection.mutable.ListBuffer[Int]
buffer += 1
buffer += 2
val list = buffer.toList

回答by oxbow_lakes

It's worth pointing out that Listhas a very specific meaning in scala, which is not equivalent to the java.util.Listinterface. Listis a sealed, abstract class representing a recursivedata-structure which has a headand a tail. (There do exist Java list-like structures in scala, some of which are mutable.)

值得指出的是,List在scala中有非常具体的含义,并不等同于java.util.List接口。List是一个密封的抽象类,表示具有headtail递归数据结构。(Scala 中确实存在类似 Java 列表的结构,其中一些是可变的。)

Scala's Lists are immutable; modifying a list in any way is not possible, although you can create a new list be prepending to an existing one (which gives a new object back). Even though they are immutable, the structure is no more expensivein terms of object creation than, say, appending to a java.util.LinkedList

Scala 的Lists 是不可变的;以任何方式修改列表都是不可能的,尽管您可以在现有列表之前创建一个新列表(这会返回一个新对象)。尽管它们是不可变的,但就对象创建而言,该结构并不比追加到一个对象更昂贵java.util.LinkedList

The +method has been deprecated for good reason because it is inefficient; instead use:

+方法已被弃用,因为它效率低下;而是使用:

val newList = theList ::: List(toAppend)

I suppose a different way would be to prepend with 2 reversals:

我想另一种方法是在前面加上 2 个逆转:

val newList = (toAppend :: theList.reverse).reverse

I doubt this is any more efficient! In general, if I want appendbehaviour, I use prependand then reverse(at the point of needing to access the list):

我怀疑这是否更有效率!一般来说,如果我想要追加行为,我使用prepend然后reverse(在需要访问列表时):

val newList = toAppend :: theList
//much later! I need to send the list somewhere...
target ! newList.reverse

回答by Daniel C. Sobral

Non deprecated way of appending an element to a List in Scala 2.7.5?

在 Scala 2.7.5 中将元素附加到列表的非弃用方法?

That does not exist, and it will never exist.

那不存在,也永远不会存在。

How do you add an element to a List in Scala 2.7.5, without creating a new List and without using a deprecated solution.

如何在 Scala 2.7.5 中向 List 添加元素,而不创建新 List 并且不使用已弃用的解决方案。

Use :::

使用::

val newList = element :: oldList

Or, if listis a var,

或者,如果listvar

list ::= element

It does not create a new List(though, it creates a new ::, also known as cons), and it adds an element to it.

它不会创建新的List(不过,它会创建一个新的::,也称为cons),并且会向其添加一个元素。

If you want to append elements to a sequence without creating a new sequence, use a mutable data structure.

如果您想在不创建新序列的情况下将元素追加到序列中,请使用可变数据结构。

回答by Ben James

The +=method on a list is deprecated because it adds an element to the tail, which is expensive. The least expensive way of adding an element to a list is to add to the head using ::=.

+=不推荐使用列表上的方法,因为它向尾部添加了一个元素,这很昂贵。将元素添加到列表的最便宜的方法是使用::=.

So the deprecation warning is a subtle hint that you should redesign your program to work by prepending instead of appending:

因此,弃用警告是一个微妙的提示,您应该通过添加而不是附加来重新设计程序以使其工作:

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)

(Note that ::=and +=on a varare not real methods, but sugar for l = l :: elem, etc)

(请注意,::=+=on avar不是真正的方法,而是用于l = l :: elem等的糖)

回答by James McMahon

The following is not true for certain operations List implementation. Thanks to sschaef for the correction.

以下不适用于某些操作 List 实现。感谢 sschaef 的更正。



A very important point that I haven't seen mentioned here is that creating a new collection from another collection necessarily isn't as expensive in Scala as it is in Java. This concept is called persistence. Daniel Spiewak lays it out in his article, http://www.codecommit.com/blog/scala/scala-collections-for-the-easily-bored-part-1.

我在这里没有看到的一个非常重要的点是,从另一个集合创建一个新集合在 Scala 中不一定像在 Java 中那样昂贵。这个概念称为持久性。Daniel Spiewak 在他的文章http://www.codecommit.com/blog/scala/scala-collections-for-the-easily-bored-part-1 中阐述了这一点。

Here is a snippet of the relevant section,

这是相关部分的片段,

Of course, the natural question which comes to mind is, what about performance? If each invocation actually creates a brand new Set for every recursive call, doesn't that require a lot of inefficient object copying and heap operations? Well, as it turns out, this isn't really the case. Yes, a new instance must be created at each turn, which is is a comparatively expensive operation on the JVM, but almost nothing is being copied. All of Scala's immutable data structures have a property known as persistence, which means that you don't copy the data out of the old container when creating a new, you just have the new reference the old and treat all of its contents as if they were its own.

当然,想到的自然问题是,性能怎么样?如果每次调用实际上为每次递归调用都创建了一个全新的 Set,那岂不是需要大量低效的对象复制和堆操作?好吧,事实证明,事实并非如此。是的,每次都必须创建一个新实例,这是 JVM 上相对昂贵的操作,但几乎没有复制任何内容。Scala 的所有不可变数据结构都有一个称为持久性的属性,这意味着您在创建新容器时不会从旧容器中复制数据,您只需将新引用作为旧容器,并将其所有内容视为它们是它自己的。

So while it will be less expensive to use a mutable list it isn't as much of a concern as it is under Java.

因此,虽然使用可变列表的成本会更低,但它不像在 Java 下那样令人担忧。