【发布时间】:2012-01-19 08:42:16
【问题描述】:
我正在寻找将collection.mutable.Seq[T] 转换为collection.immutable.Seq[T] 的最佳方法。
【问题讨论】:
标签: scala collections
我正在寻找将collection.mutable.Seq[T] 转换为collection.immutable.Seq[T] 的最佳方法。
【问题讨论】:
标签: scala collections
如果您还使用Set 和Map,您也可以尝试这些,以TreeSet 为例。
import scala.collection.mutable
val immutableSet = TreeSet(blue, green, red, yellow)
//converting a immutable set to a mutable set
val mutableSet = mutable.Set.empty ++= immutableSet
//converting a mutable set back to immutable set
val anotherImmutableSet = Set.empty ++ mutableSet
以上示例来自《Scala 编程》一书
【讨论】:
如果要将ListBuffer 转换为List,请使用.toList。我提到这一点是因为特定的转换是在恒定时间内执行的。但请注意,进一步使用 ListBuffer 将导致其内容首先被复制。
否则,您可以使用collection.immutable.Seq(xs: _*),假设 xs 是可变的,因为您不太可能以任何其他方式获得更好的性能。
【讨论】:
toList(或者toStream,如果你想要一个LinearSeq)是首选的方式,因为你可以确定你得到的东西是不可变的(因为List和Stream是)。如果您想要一个不可变的IndexedSeq,则没有toVector 方法,但似乎toIndexedSeq 为您提供了一个Vector(它是不可变的),如果不是所有时间的话。
另一种方法是使用breakOut。这将查看您在返回类型中的目标类型,并在可能的情况下帮助您。例如
scala> val ms = collection.mutable.Seq(1,2,3)
ms: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 3)
scala> val r: List[Int] = ms.map(identity)(collection.breakOut)
r: List[Int] = List(1, 2, 3)
scala> val r: collection.immutable.Seq[Int] = ms.map(identity)(collection.breakOut)
r: scala.collection.immutable.Seq[Int] = Vector(1, 2, 3)
有关这种黑魔法的更多信息,请喝点浓咖啡并查看this question。
【讨论】:
如指定:
def convert[T](sq: collection.mutable.Seq[T]): collection.immutable.Seq[T] =
collection.immutable.Seq[T](sq:_*)
加法
本机方法使用起来有点棘手。它们已在scala.collection.Seq 上定义,您必须仔细查看它们是否返回collection.immutable 或collection.mutable。例如.toSeq 返回一个collection.Seq,它不保证可变性。 .toIndexedSeq 然而,返回一个 collection.immutable.IndexedSeq 所以它似乎很好用。不过,我不确定这是否真的是预期的行为,因为还有一个 collection.mutable.IndexedSeq。
最安全的方法是手动将其转换为预期的集合,如上所示。在使用原生转换时,我认为最好添加类型注释,包括 (mutable/immutable) 以确保返回正确的集合。
【讨论】:
.toIndexedSeq 或 .toStream 这样的原生方法呢?我只是不确定哪个是最佳解决方案。