Подтвердить что ты не робот

Преобразование изменчивой коллекции в неизменяемую

Я ищу лучший способ преобразования collection.mutable.Seq[T] в collection.immutable.Seq[T].

4b9b3361

Ответ 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