Giả sử chúng tôi có một số Map[A,B]
. Để làm rõ: Tôi luôn luôn đề cập đến một bất biến Map
.
mapValues
có chức năng B => C
, trong đó C
là loại mới cho giá trị.
transform
có chức năng (A, B) => C
, trong đó C
cũng là loại cho giá trị.
Vì vậy, cả hai kết quả sẽ là Map[A,C]
.
Tuy nhiên, với chức năng transform
bạn có thể ảnh hưởng đến kết quả của các giá trị mới bằng giá trị khóa của chúng.
Ví dụ:
val m = Map("a" -> 2, "b" -> 3)
m.transform((key, value) => key + value) //Map[String, String](a -> a2, b -> b3)
Việc làm này với mapValues
sẽ khá khó khăn.
Sự khác biệt tiếp theo là transform
là nghiêm ngặt, trong khi mapValues
sẽ chỉ cung cấp cho bạn chế độ xem, chế độ này sẽ không lưu trữ các phần tử được cập nhật. Nó trông giống như thế này:
protected class MappedValues[C](f: B => C) extends AbstractMap[A, C] with DefaultMap[A, C] {
override def foreach[D](g: ((A, C)) => D): Unit = for ((k, v) <- self) g((k, f(v)))
def iterator = for ((k, v) <- self.iterator) yield (k, f(v))
override def size = self.size
override def contains(key: A) = self.contains(key)
def get(key: A) = self.get(key).map(f)
}
(lấy từ https://github.com/scala/scala/blob/v2.11.2/src/library/scala/collection/MapLike.scala#L244)
Vì vậy, hiệu suất-khôn ngoan nó phụ thuộc những gì là hiệu quả hơn. Nếu f
là tốn kém và bạn chỉ truy cập vào một số yếu tố của bản đồ kết quả, mapValues
có thể tốt hơn, vì f
chỉ được áp dụng theo yêu cầu. Nếu không, tôi sẽ dính vào map
hoặc transform
.
transform
cũng có thể được thể hiện bằng map
. Giả m: Map[A,B]
và f: (A,B) => C
, sau đó
m.transform(f)
tương đương với m.map{case (a, b) => (a, f(a, b))}