Я ищу лучший способ преобразования collection.mutable.Seq[T]
в collection.immutable.Seq[T]
.
Преобразование изменчивой коллекции в неизменяемую
Ответ 1
Если вы хотите преобразовать ListBuffer
в List
, используйте .toList
. Я упоминаю об этом, потому что это конкретное преобразование выполняется в постоянное время. Обратите внимание, однако, что любое дальнейшее использование ListBuffer
приведет к тому, что его содержимое будет скопировано первым.
В противном случае вы можете сделать collection.immutable.Seq(xs: _*)
, предполагая, что xs изменен, поскольку вы вряд ли получите лучшую производительность любым другим способом.
Ответ 2
Как указано:
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
возвращает a collection.Seq
, который не дает никаких гарантий относительно изменчивости. Тем не менее, .toIndexedSeq
возвращает a collection.immutable.IndexedSeq
, поэтому кажется, что это нормально. Я не уверен, хотя, если это действительно предполагаемое поведение, так как есть также collection.mutable.IndexedSeq
.
Самый безопасный подход - это преобразовать его вручную в предполагаемую коллекцию, как показано выше. При использовании собственного преобразования я считаю, что лучше всего добавить аннотацию типа, включая (mutable
/immutable
), чтобы гарантировать верную сборку.
Ответ 3
toList
(или toStream
, если вы хотите, чтобы он ленился) являются предпочтительным способом, если вы хотите LinearSeq
, так как вы можете быть уверены, что вы вернетесь, является неизменным (потому что List и Stream). Нет метода toVector
, если вы хотите неизменный IndexedSeq
, но кажется, что toIndexedSeq
дает вам вектор (который является неизменным) больше всего, если не все время.
Другой способ - использовать 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)
Для получения дополнительной информации о такой черной магии, получите сильный кофе и посмотрите этот вопрос.
Ответ 4
Если вы также работаете с 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