我有一种情况,我将单个元素列表传递给方法.在此方法中,列表中的单个元素增加1.因此,在方法调用之后,将修改列表第一个元素(递增1).
代码是这样的:
val ct = List(5)
someMethod(ct)
println (ct(0))
// should print 6
Run Code Online (Sandbox Code Playgroud)
......
//within somethod, I incrment the element like:
def someMethod(ct: List[Int}) {
ct(0) = ct(0) + 1
}
Run Code Online (Sandbox Code Playgroud)
当然上面的代码在Scala中不起作用.我查看了ListBuffer,但我发现scala doc难以理解.Scala doc分为2组:Type Member和Value Members.在类型成员中有类WithFiler,值成员有许多方法.我如何使用WithFiler(可能与此问题没有直接关系,但我想了解如何使用scala doc).
如果我想要具有非常高的性能(someMethod被称为数百万次),ListBuffer似乎是解决这个问题的正确方法(如果我错了,请纠正我).
那么如果ListBuffer是正确的列表类型,如果不是解决方案,如何解决上述问题呢?
par*_*tic 10
在scala中,表达式为:
ct(0) = ct(0) + 1
Run Code Online (Sandbox Code Playgroud)
被重写为:
ct.update( 0, ct.apply(0) + 1 )
Run Code Online (Sandbox Code Playgroud)
update没有为超类型定义方法,List因为列表可以是不可变的.但是,这是函数参数的类型.
所以你必须只使用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)
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果您需要通过索引访问元素,请使用ArrayBuffer.它应该像java一样工作ArrayList.
最后,如果你不需要考虑WithFilter事情.只需使用该filter方法.
这有一种过早的微观优化的气味.
虽然使用可变性(包括优化)有正当理由,但您没有说明为什么您认为您的使用有效,或者您尝试解决的更大问题.特别是,不可变列表在获取尾部并增加新头部时非常有效 - 100%的非头部元素将在原始列表和新列表之间共享.
如上所述,满足您要求的最干净的解决方案是忘记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
Run Code Online (Sandbox Code Playgroud)
另一方面,如果这是性能热点,并且您无法通过更改算法来识别任何提高性能的方法,那么您将需要使用Array
Array是JVM上唯一的已知集合类型.因此,您可以直接使用数组中的基元,并避免其他集合类型必须应对的装箱/取消装箱.
这里的优势与可变性和不变性无关; 取消装箱/装箱的性能成本远远高于使用不可变列表的性能成本(如果有的话).
| 归档时间: |
|
| 查看次数: |
16466 次 |
| 最近记录: |