How to use ListBuffer in scala?
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).
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 ListBuffer but 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).
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).
So how to solve开发者_如何学C above problem if ListBuffer is the right type of list and if not what is the solution?
In scala, the expression:
ct(0) = ct(0) + 1
is rewritten as:
ct.update( 0, ct.apply(0) + 1 )
Method update
is not defined for supertype List
because lists can be immutable. However, that's the type of the function argument.
So you must use only ListBuffers (or a mutable supertype):
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
.
Finally, If you don't need to think about WithFilter
stuff. Just use the filter
method.
If performance is a main goal and maximal size of collection is known, you can use Array which maps directly to java array.
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 very efficient when taking the tail and prepending a new head - 100% of the non-head elements will be shared between the original and new List.
As presented, the cleanest solution for your requirements is to forget about ListBuffer
, stick with an immutable List
and implement someMethod
without recourse to side-effects.
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 is a 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 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.
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.
You can certainly rewrite the above to use ListBuffer
, but if all you want is call-by-reference semantics for a single Int
it's not necessarily the most efficient solution. ArrayBuffer
should be a bit better. You could also do something like this:
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
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 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.
精彩评论