Làm cách nào tôi có thể chuyển đổi immutable.Map
sang mutable.Map
trong Scala để có thể cập nhật các giá trị trong Map
?
Làm cách nào tôi có thể chuyển đổi immutable.Map
sang mutable.Map
trong Scala để có thể cập nhật các giá trị trong Map
?
Câu trả lời:
Cách sạch sẽ nhất là sử dụng mutable.Map
nhà máy sản xuất kỳ đà . Không giống như ++
cách tiếp cận, cách này sử dụng CanBuildFrom
cơ chế và do đó có khả năng hiệu quả hơn nếu mã thư viện được viết để tận dụng lợi thế này:
val m = collection.immutable.Map(1->"one",2->"Two")
val n = collection.mutable.Map(m.toSeq: _*)
Điều này hoạt động vì a Map
cũng có thể được xem như một chuỗi các Cặp.
: _*
giống như kiểu ký tự, cho trình biên dịch biết chính xác kiểu cần gán cho một biểu thức nhất định. Bạn có thể nghĩ về nó ở đây như nói "lấy chuỗi này và coi nó như một số tham số vararg."
val myImmutableMap = collection.immutable.Map(1->"one",2->"two")
val myMutableMap = collection.mutable.Map() ++ myImmutableMap
O(1)
từng bước. Điều này có vẻ như vậy O(n)
, mặc dù điều đó tất nhiên phụ thuộc vào mức độ thông minh của việc triển khai ++
.
O(n)
. Trong giới hạn khi bạn thay đổi mọi thứ, điều đó phải xảy ra O(n)
, mặc dù bạn có thể cố gắng trì hoãn việc tạo bản sao mới để tiết kiệm thời gian hoặc bạn tăng gấp đôi thời gian truy cập của mình bằng cách đọc các tập thay đổi thay vì bản đồ gốc. Cái nào hoạt động tốt nhất có lẽ phụ thuộc vào trường hợp sử dụng của bạn.
Làm thế nào về việc sử dụng collection.breakOut?
import collection.{mutable, immutable, breakOut}
val myImmutableMap = immutable.Map(1->"one",2->"two")
val myMutableMap: mutable.Map[Int, String] = myImmutableMap.map(identity)(breakOut)
mutable.Map#apply
với một tấm boilerplate hơn một chút.
Bắt đầu Scala 2.13
, thông qua các nhà xây dựng nhà máy áp dụng với .to(factory)
:
Map(1 -> "a", 2 -> "b").to(collection.mutable.Map)
// collection.mutable.Map[Int,String] = HashMap(1 -> "a", 2 -> "b")
Có một biến thể để tạo một biến thể trống có Map
các giá trị mặc định được lấy từ bất biến Map
. Bạn có thể lưu trữ một giá trị và ghi đè giá trị mặc định bất kỳ lúc nào:
scala> import collection.immutable.{Map => IMap}
//import collection.immutable.{Map=>IMap}
scala> import collection.mutable.HashMap
//import collection.mutable.HashMap
scala> val iMap = IMap(1 -> "one", 2 -> "two")
//iMap: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,one), (2,two))
scala> val mMap = new HashMap[Int,String] {
| override def default(key: Int): String = iMap(key)
| }
//mMap: scala.collection.mutable.HashMap[Int,String] = Map()
scala> mMap(1)
//res0: String = one
scala> mMap(2)
//res1: String = two
scala> mMap(3)
//java.util.NoSuchElementException: key not found: 3
// at scala.collection.MapLike$class.default(MapLike.scala:223)
// at scala.collection.immutable.Map$Map2.default(Map.scala:110)
// at scala.collection.MapLike$class.apply(MapLike.scala:134)
// at scala.collection.immutable.Map$Map2.apply(Map.scala:110)
// at $anon$1.default(<console>:9)
// at $anon$1.default(<console>:8)
// at scala.collection.MapLike$class.apply(MapLike.scala:134)....
scala> mMap(2) = "three"
scala> mMap(2)
//res4: String = three
Lưu ý (xem nhận xét của Rex Kerr): Bạn sẽ không thể xóa các phần tử đến từ bản đồ bất biến:
scala> mMap.remove(1)
//res5: Option[String] = None
scala> mMap(1)
//res6: String = one