Как использовать изменяемые коллекции в Scala
Я думаю, что я не могу понять, как работают изменяемые коллекции. Я ожидаю, что изменяющиеся коллекции будут затронуты, применяя карту к ним или добавляя новые элементы, однако:
scala> val s: collection.mutable.Seq[Int] = collection.mutable.Seq(1)
s: scala.collection.mutable.Seq[Int] = ArrayBuffer(1)
scala> s :+ 2 //appended an element
res32: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2)
scala> s //the original collection is unchanged
res33: scala.collection.mutable.Seq[Int] = ArrayBuffer(1)
scala> s.map(_.toString) //mapped a function to it
res34: scala.collection.mutable.Seq[java.lang.String] = ArrayBuffer(1)
scala> s //original is unchanged
res35: scala.collection.mutable.Seq[Int] = ArrayBuffer(1)
//maybe mapping a function that changes the type of the collection shouldn't work
//try Int => Int
scala> s.map(_ + 1)
res36: scala.collection.mutable.Seq[Int] = ArrayBuffer(2)
scala> s //original unchanged
res37: scala.collection.mutable.Seq[Int] = ArrayBuffer(1)
Такое поведение не кажется отдельным от неизменных коллекций, так когда же они ведут себя отдельно?
4 ответа
Для неизменяемых и изменяемых коллекций, :+
а также +:
создавать новые коллекции. Если вы хотите, чтобы изменяемые коллекции автоматически увеличивались, используйте +=
а также +=:
методы, определенные collection.mutable.Buffer
,
Так же, map
возвращает новую коллекцию - ищите transform
изменить коллекцию на месте.
map
Операция применяет данную функцию ко всем элементам коллекции и создает новую коллекцию.
Операция, которую вы ищете, называется transform
, Вы можете думать об этом как о месте map
за исключением того, что функция преобразования должна быть типа a -> a
вместо a -> b
,
scala> import collection.mutable.Buffer
import collection.mutable.Buffer
scala> Buffer(6, 3, 90)
res1: scala.collection.mutable.Buffer[Int] = ArrayBuffer(6, 3, 90)
scala> res1 transform { 2 * }
res2: res1.type = ArrayBuffer(12, 6, 180)
scala> res1
res3: scala.collection.mutable.Buffer[Int] = ArrayBuffer(12, 6, 180)
Как отмечают другие,
map
и методы возвращают измененную копию коллекции. В более общем смысле все методы, определенные в коллекциях из
scala.collection
пакет никогда не изменит коллекцию на месте, даже если динамический тип коллекции из
scala.collection.mutable
. Чтобы изменить коллекцию на месте, найдите методы, определенные в
scala.collection.mutable._
но не в
scala.collection._
.
Например,
:+
определен в , поэтому он никогда не будет выполнять модификацию на месте, даже если динамический тип — это . Однако,
+=
, который определен в
scala.collection.mutable.ArrayBuffer
и не в
scala.collection.Seq
, изменит коллекцию на месте.
map
Метод никогда не изменяет коллекцию, в которой вы его вызываете. Система типов не позволит такой реализации карты на месте существовать - если только вы не изменили сигнатуру типа, так что для некоторого типа Collection[A]
Вы могли только отобразить, используя функцию типа A => A
,
(Редактировать: как уже указывалось в других ответах, существует такой метод, который называется transform
!)
Так как map
создает новую коллекцию, вы можете перейти от Collection[A]
к Collection[B]
используя функцию A => B
, что гораздо полезнее.