将可变集合转换为不可变集合

时间:2011-12-13 13:12:35

标签: scala collections

我正在寻找将collection.mutable.Seq[T]转换为collection.immutable.Seq[T]的最佳方式。

4 个答案:

答案 0 :(得分:39)

如果您想将ListBuffer转换为List,请使用.toList。我之所以提到这一点是因为特定转换是在恒定时间内执行的。但请注意,ListBuffer的任何进一步使用都将导致首先复制其内容。

否则,你可以做collection.immutable.Seq(xs: _*),假设xs是可变的,因为你不可能以任何其他方式获得更好的性能。

答案 1 :(得分:15)

按照规定:

def convert[T](sq: collection.mutable.Seq[T]): collection.immutable.Seq[T] = 
  collection.immutable.Seq[T](sq:_*)

<强>加成

本机方法使用起来有点棘手。它们已在scala.collection.Seq上定义,您必须仔细查看是否返回collection.immutablecollection.mutable。例如.toSeq返回collection.Seq,但不保证可变性。但是,.toIndexedSeq会返回collection.immutable.IndexedSeq,因此使用似乎没问题。我不确定,如果这确实是预期的行为,因为还有一个collection.mutable.IndexedSeq

最安全的方法是将其手动转换为预期的集合,如上所示。使用本机转换时,我认为最佳做法是添加包含(mutable / immutable)的类型注释,以确保返回正确的集合。

答案 2 :(得分:6)

如果你想要toList

toStream(或LinearSeq如果你想要它是懒惰的)是首选方式,因为你可以确定你得到的是不可变的(因为List和流是)。如果你想要一个不可变的toVector,那就没有IndexedSeq方法了,但似乎toIndexedSeq给你一个Vector(它是不可变的),如果不是所有的话那么。

另一种方法是使用breakOut。这将查看您在返回类型中的目标类型,如果可能,请您。 e.g。

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

答案 3 :(得分:2)

如果您还使用SetMap,也可以使用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编程