2012-07-31 51 views
24

當連接兩個不可改變的地圖,似乎是正確的操作數的元素將「覆蓋」左某的元素:連接兩個不可變的映射 - 哪些元素是首選?

scala> List((1, 2), (5, 6)).toMap ++ List((5, 9)).toMap 
res13: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 5 -> 9) 

scala> List((5, 9)).toMap ++ List((1, 2), (5, 6)).toMap 
res14: scala.collection.immutable.Map[Int,Int] = Map(5 -> 6, 1 -> 2) 

我想知道,如果這是Scala中的一個規則?

從Scala API我找不出這個問題。

回答

20

是,這種行爲是恆定

+2

謝謝。如果你也可以告訴我爲什麼(或者在定義規則的地方給出了參考),你會得到接受的答案。 :-) – 2012-07-31 15:32:32

+2

在大多數情況下,'++'的實現依賴於'+',它依次依賴於'updated'和[this](http://www.scala-lang.org/api/current /scala/collection/immutable/Map.html)scaladoc聲明'updated'返回一個用新值更新的新的不可變映射。是的,我知道,這不是一個絕對的證據,所以你可能不應該關閉這個問題,等待更好的參考。儘管如此,「Java Map」引用仍然是公牛命中。 – 2012-07-31 16:09:14

11

Map.++is defined as

override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): immutable.Map[A, B1] = 
    ((repr: immutable.Map[A, B1]) /: xs.seq) (_ + _) 

其中repr是當前地圖和xs.seq讓你存儲在你傳遞給++地圖的雙/映射的序列。


Map./:is described as

def /:[B](z: B)(op: (B, (A, B)) ⇒ B): B 

Applies a binary operator to a start value and all elements of this 
immutable map, going left to right. 

Note: /: is alternate syntax for foldLeft; 
z /: xs is the same as xs foldLeft z. 

注意,它沒有指定什麼 「從左至右」 是指無序地圖。


下面舉例說明通過重新實現++與調試增強它println語句在幕後發生了什麼:

val m1 = Map(1 -> "A", 2 -> "B", 3 -> "C") 
val m2 = Map(2 -> "X", 3 -> "Y", 4 -> "Z") 

println(m1.repr) 
    /* Map(1 -> A, 2 -> B, 3 -> C) */ 
println(m1.repr.getClass.getName) 
    /* scala.collection.immutable.Map$Map3 */ 

def ++[K, V](ts: Map[K, V], xs: Map[K, V]): Map[K, V] = 
    (ts /: xs) {case (acc, entry) => 
       println("acc = " + acc) 
       println("entry = " + entry) 
       acc + entry 
       } 

val m3 = ++(m1, m2) 
    /* 
    acc = Map(1 -> A, 2 -> B, 3 -> C) 
    entry = (2,X) 
    acc = Map(1 -> A, 2 -> X, 3 -> C) 
    entry = (3,Y) 
    acc = Map(1 -> A, 2 -> X, 3 -> Y) 
    entry = (4,Z) 
    */ 

println(m3) 
    /* Map(1 -> A, 2 -> X, 3 -> Y, 4 -> Z) */ 
+0

在你的方法++中,你沒有像前面解釋的那樣得到xs.seq。爲什麼是這樣? – Felix 2014-07-29 13:52:42

+0

@Felix'immutable.Map'覆蓋'def seq'返回自身,即'this','xs.seq'因此計算到與'xs'相同的地圖。我假設可以在子類中重寫'def seq',但是我不知道集合庫的內部設計是否足夠用於甚至是必要的。 – 2014-09-02 12:21:56

相關問題