Преобразование изменяемой коллекции в неизменяемую - PullRequest
29 голосов
/ 13 декабря 2011

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

Ответы [ 4 ]

39 голосов
/ 13 декабря 2011

Если вы хотите преобразовать ListBuffer в List, используйте .toList.Я упоминаю об этом, потому что конкретное преобразование выполняется за постоянное время .Тем не менее, обратите внимание, что любое дальнейшее использование ListBuffer приведет к тому, что его содержимое будет скопировано первым.

В противном случае вы можете выполнить collection.immutable.Seq(xs: _*), предполагая, что xs изменчив, так как вы вряд ли получите лучшую производительностьлюбым другим способом.

15 голосов
/ 13 декабря 2011

Как указано:

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), чтобы обеспечить возврат правильной коллекции.

6 голосов
/ 13 декабря 2011

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)

Для получения дополнительной информации о такой черной магии, получите крепкий кофе и посмотрите этот вопрос .

2 голосов
/ 02 февраля 2017

Если вы также работаете с 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...