Załóżmy, że mamy Map[A,B]
. Dla wyjaśnienia: zawsze mam na myśli niezmienny Map
.
mapValues
przyjmuje funkcję B => C
, gdzie C
jest nowym typem wartości.
transform
przyjmuje funkcję (A, B) => C
, gdzie ten C
jest również typem dla wartości.
Więc oba skutkują Map[A,C]
.
Jednak z funkcją transform
możesz wpływać na wynik nowych wartości przez wartość ich kluczy.
Na przykład:
val m = Map("a" -> 2, "b" -> 3)
m.transform((key, value) => key + value) //Map[String, String](a -> a2, b -> b3)
Robi to z mapValues
będzie dość trudne.
Następną różnicą jest to, że transform
jest ścisłe, natomiast mapValues
daje tylko widok, który nie będzie przechowywać zaktualizowanych elementów. Wygląda to tak:
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)
}
(zaczerpnięte z https://github.com/scala/scala/blob/v2.11.2/src/library/scala/collection/MapLike.scala#L244)
Więc wydajność mądry to zależy od tego, co jest bardziej skuteczne. Jeśli f
jest kosztowny i masz dostęp tylko do kilku elementów wynikowej mapy, mapValues
może być lepszy, ponieważ f
jest stosowany tylko na żądanie. W przeciwnym razie trzymałbym się map
lub transform
.
transform
można również wyrazić za pomocą map
. Zakładamy m: Map[A,B]
i f: (A,B) => C
, następnie
m.transform(f)
jest równoważna m.map{case (a, b) => (a, f(a, b))}