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

Nik*_*kov 30 collections scala

我正在寻找一个转化的最佳途径collection.mutable.Seq[T]collection.immutable.Seq[T].

Dan*_*ral 39

如果你想转换ListBuffer成a List,请使用.toList.我提到这一点,因为那个特定的转换是在固定时间内进行.但请注意,任何进一步使用ListBuffer将导致其内容被首先复制.

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


Deb*_*ski 15

作为指定:

def convert[T](sq: collection.mutable.Seq[T]): collection.immutable.Seq[T] = 
  collection.immutable.Seq[T](sq:_*)
Run Code Online (Sandbox Code Playgroud)

加成

本机方法使用起来有点棘手.它们已被定义scala.collection.Seq,您必须仔细查看它们是否返回a collection.immutable或a collection.mutable.例如,.toSeq返回a collection.Seq不保证可变性..toIndexedSeq然而,返回一个collection.immutable.IndexedSeq所以它似乎很好用.我不确定,如果这确实是预期的行为,因为还有一个collection.mutable.IndexedSeq.

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


Lui*_*hys 6

toList(或者,toStream如果你想要它懒惰)是你想要的首选方式LinearSeq,因为你可以确定你得到的是不可变的(因为List和Stream是).toVector如果你想要一个不可变的方法,那就没有方法IndexedSeq,但它似乎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)
Run Code Online (Sandbox Code Playgroud)

有关这种黑魔法的更多信息,请获取一些浓咖啡并看到这个问题.