2012-04-04 17 views
0

おそらく簡単に答えられる質問ですが、APIから満足のいく答えが見つかりませんでした。私は素敵なコードを書こうとはしていませんが、特定のものがどのように機能するかについてもっと学びたいと思っています:予期せぬスカラのマップとループの副作用

私は最初のHashMapを作成しました。任意のリストから、マップを使用してHashMapのリストを作成したいと思います。私は、(キー、値)ペアをHashMapに.map関数内で追加します。したがって、このリストから連続したインデックスでは、格納されたHashMapのサイズは1つ増えます(リストi).size == list(i + 1).size - iはすべて1になります。

しかし、次のコードをスニップして、私はすべてのマップが等しい(つまり完全なHashMap)リストを取得します。私が成長している最初のHashMapを印刷すると、すべてが正しいように見えます。私が期待したもの

scala> import scala.collection.mutable.HashMap 

val m = new HashMap[Int, Int] 

List(1,2,3,4) map {e => 
    println(m) 
    val newM = m += e -> (e+2) 
    newM 
} 
Map() 
Map(1 -> 3) 
Map(1 -> 3, 2 -> 4) 
Map(3 -> 5, 1 -> 3, 2 -> 4) 

import scala.collection.mutable.HashMap 
m: scala.collection.mutable.HashMap[Int,Int] = Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4) 
res7: List[scala.collection.mutable.HashMap[Int,Int]] = List(Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4),  Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4)) 

一覧(地図(1のようなものだった - > 2)、地図(1 - > 2、2 - > 4)、地図(1 - > 2、2 - > (1→2、4→3→5、4→6))

generative forループの結果を使用した同等のバージョンまったく同じ結果に:

scala> for { 
    i <- 1 to 4 
    val newM = m += i -> (i+2) 
} yield newM 
res10: scala.collection.immutable.IndexedSeq[scala.collection.mutable.HashMap[Int,Int]] = Vector(Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4)) 

scala> for (i <- 1 to 4) yield { 
    val newM = m += i -> (i+2) 
    println(m) 
    newM 
} 
Map(1 -> 3) 
Map(1 -> 3, 2 -> 4) 
Map(3 -> 5, 1 -> 3, 2 -> 4) 
Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4) 
res11: scala.collection.immutable.IndexedSeq[scala.collection.mutable.HashMap[Int,Int]] = Vector(Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4)) 

私は基本的なステップをしないのですと仮定し、私はちょうどその表示されません。さらなる助けに感謝します!

次の質問:明らかに(キー、値)のペアが印刷される順序は同じです(ただし、要素の順序ではありませんが、マップからこれを期待するわけではありません。自然です)。ペアが保存されているときにバックグラウンドで何が起こるのでしょうか?

答えて

4

mは、変更可能なHashMapです。

+=メソッドは、全く同じマップに新しい要素を追加し、マップを返します。

マップにはnewMという名前が付けられていますが、これは赤いニシンです!それはまったく同じマップmです。だから彼らはすべてただmです。

実際にコピーを希望される場合は、(例:val newM = (m += e -> (e+2)).clone)にcloneと電話することができます。

それとも、あなたが行くようにあなたが不変マップを構築したい場合、あなたはscanメソッドを使用することができます(この場合、空のマップで)アイテムを取り、上に構築されています

List(1,2,3,4).scanLeft(collection.immutable.HashMap[Int,Int]()){ (m,e) => m + (e -> (e+2)) } 

それはステップバイステップで、あなたに全体の歴史を返すに行うのとき:

res7: List[scala.collection.immutable.HashMap[Int,Int]] 
    = List(Map(), Map(1 -> 3), Map(1 -> 3, 2 -> 4), 
     Map(1 -> 3, 2 -> 4, 3 -> 5), Map(1 -> 3, 2 -> 4, 3 -> 5, 4 -> 6)) 

をいっそのこと、することができます

List(1,2,3,4).map(e => e -> (e+2)).toMap 

ビルドプロセスを気にせずに最終的な地図を取得できます。