如何在 Scala 中使用 ListBuffer?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6570103/
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 03:10:12  来源:igfitidea点击:

How to use ListBuffer in scala?

scala

提问by rjc

I have a situation where I am passing a single element list to a method. Within this method, the single element in the list is incremented by one. So that after method call, the list first element is modified ( incremented by one).

我有一种情况,我将单个元素列表传递给一个方法。在此方法中,列表中的单个元素递增 1。这样在方法调用后,列表的第一个元素被修改(增加一)。

Code is like this:

代码是这样的:

val ct = List(5)

someMethod(ct)

println (ct(0))

// should print 6

......

......

//within somethod, I incrment the element like:
def someMethod(ct: List[Int}) {
    ct(0) = ct(0) + 1
}

Of course above code does not work in Scala. I looked at ListBufferbut I find the scala doc hard to follow. Scala doc is divided into 2 groups: Type Members and Value Members. In type member there is class WithFiler and value members has many methods. How can I use WithFiler ( probably not directly related to this question but I want to understand how to make use of scala doc).

当然,上面的代码在 Scala 中不起作用。我查看了ListBuffer,但我发现难以理解Scala 文档。Scala 文档分为两组:类型成员和值成员。在类型成员中有类 WithFiler 和值成员有很多方法。我如何使用 WithFiler(可能与这个问题没有直接关系,但我想了解如何使用 scala doc)。

ListBuffer seems to be the right solution for this problem if I want to have very high performance (the someMethod is called millions of times) ( correct me if I am wrong).

如果我想要非常高的性能(someMethod 被调用数百万次)(如果我错了,请纠正我),ListBuffer 似乎是这个问题的正确解决方案。

So how to solve above problem if ListBuffer is the right type of list and if not what is the solution?

那么如果 ListBuffer 是正确的列表类型,如何解决上述问题,如果不是,解决方案是什么?

回答by paradigmatic

In scala, the expression:

在 Scala 中,表达式:

ct(0) = ct(0) + 1

is rewritten as:

改写为:

ct.update( 0, ct.apply(0) + 1 )

Method updateis not defined for supertype Listbecause lists can be immutable. However, that's the type of the function argument.

update没有为超类型定义方法,List因为列表可以是不可变的。但是,这是函数参数的类型。

So you must use only ListBuffers (or a mutable supertype):

因此,您必须仅使用 ListBuffers(或可变超类型):

def someMethod(ct: ListBuffer[Int]) {
  ct(0) = ct(0) + 1
}

scala> val lst = ListBuffer( 5 )
  lst: scala.collection.mutable.ListBuffer[Int] = ListBuffer(5)
scala> someMethod( lst )
scala> lst
  res2: scala.collection.mutable.ListBuffer[Int] = ListBuffer(6)

By the way, if you need to access elements by indices, use instead an ArrayBuffer. It should work as java ArrayList.

顺便说一句,如果您需要按索引访问元素,请改用ArrayBuffer. 它应该像 java 一样工作ArrayList

Finally, If you don't need to think about WithFilterstuff. Just use the filtermethod.

最后,如果你不需要考虑的WithFilter东西。就用这个filter方法吧。

回答by Kevin Wright

This has the smell of a premature micro-optimisation about it.

这有一种关于它过早的微观优化的味道。

Although there are valid reasons for using mutability (including optimisation), you haven't stated why you believe your usage is valid, or the bigger problem that you're trying to solve. In particular, immutable Lists are veryefficient when taking the tail and prepending a new head - 100% of the non-head elements will be shared between the original and new List.

尽管使用可变性(包括优化)是有正当理由的,但您还没有说明为什么您认为您的使用是有效的,或者您试图解决的更大问题。特别是,不可变列表在获取尾部并添加新头部时非常有效 - 100% 的非头部元素将在原始列表和新列表之间共享。

As presented, the cleanest solution for your requirements is to forget about ListBuffer, stick with an immutable Listand implement someMethodwithout recourse to side-effects.

如上所述,满足您要求的最干净的解决方案是忘记ListBuffer,坚持不可变List和实施someMethod而不求助于副作用。

def someMethod(xs: List[Int]) = xs match {
  case h :: t => (h+1) :: t
  case Nil => Nil
}

val ct = List(5)
println (someMethod(ct).headOption getOrElse "empty list")

// should print 6


On the other hand, if this isa performance hotspot, and you can't identify any way to improve performance by changing the algorithm, then you'll want to use an Array

另一方面,如果这一个性能热点,并且您无法确定通过更改算法来提高性能的任何方法,那么您将需要使用Array

Array is the only reified collection type on the JVM. As such, you can directly work with primitives in an Array and avoid the boxing/unboxing that other collection types have to contend with.

Array 是 JVM 上唯一具体化的集合类型。因此,您可以直接使用 Array 中的原语,避免其他集合类型必须应对的装箱/拆箱。

The advantage here has nothing to do with mutability vs. immutability; the performance cost of unboxing/boxing is far higher than the performance cost (if any) of using an immutable List.

这里的优势与可变性与不变性无关;拆箱/装箱的性能成本远高于使用不可变列表的性能成本(如果有的话)。

回答by incrop

If performance is a main goal and maximal size of collection is known, you can use Array which maps directly to java array.

如果性能是主要目标并且已知集合的最大大小,则可以使用直接映射到 java 数组的 Array。

回答by Zdenek F

If you want to use ListBuffer, all you have to do is to replace word "List" in your code for "ListBuffer". However, I would avoid the side-effect function (yours someMethod: Unit) completely like naten suggests.

如果您想使用 ListBuffer,您所要做的就是将代码中的“List”替换为“ListBuffer”。但是,我会完全像 naten 建议的那样避免副作用函数(你的 someMethod:Unit)。

ListBuffer has "high performance" - however, the main purpose is adding items/modifying the collection. If I get it correctly, you just update the item in one item collection million times - Array is sufficient for that.

ListBuffer 具有“高性能”——然而,主要目的是添加项目/修改集合。如果我理解正确,您只需将一个项目集合中的项目更新数百万次 - Array 就足够了。

回答by Nate Nystrom

You can certainly rewrite the above to use ListBuffer, but if all you want is call-by-reference semantics for a single Intit's not necessarily the most efficient solution. ArrayBuffershould be a bit better. You could also do something like this:

您当然可以重写上述内容以使用ListBuffer,但如果您想要的只是单个的按引用调用语义,那么Int它不一定是最有效的解决方案。 ArrayBuffer应该会好一点。你也可以做这样的事情:

class IntCell(var x: Int)
def someMethod(ct: IntCell) {
  ct.x += 1
}

I usually try to rewrite my code to avoid using mutable collections for this kind of thing. For example, you could just return the new value:

我通常会尝试重写我的代码,以避免将可变集合用于此类事情。例如,您可以只返回新值:

def someMethod(ct: Int) = ct + 1