Scala 例 Map

ScalaにもMapがある。
http://www.scala-lang.org/api/current/scala/collection/Map
これの動作を確認してみる

オブジェクトの生成と基本のメソッド

java.util.MapとScalaのMapのメソッドの対応は、以下のようだ

java.util.Map scala.collection.Map 説明
put +
putAll ++
get ()
なし get Option型で返す
なし getOrElse
remove -

ただし、もとのMapオブジェクトは変化しない。もとのMapオブジェクトから、新しい別のMapオブジェクトが生成される。なにせ、immutableのパッケージゆえ。

scala> val map = Map(1 -> "a", 2 -> "b", 3 -> "c")
map: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> a, 2 -> b, 3 -> c)

scala> map + (4 -> "d")
res6: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> a, 2 -> b, 3 -> c, 4 -> d)

scala> map
res7: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> a, 2 -> b, 3 -> c)

scala> map - (2)
res8: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> a, 3 -> c)

scala> map
res9: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> a, 2 -> b, 3 -> c)

矢印 -> を何度もつかっている。これをつかうと、Tupleができるようだ。だから、4 -> "d"と(4, "d")は、Mapに+すると同じ結果になる

scala> 4 -> "d"
res21: (Int, java.lang.String) = (4,d)

scala> map + ((4, "d"))
res23: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> a, 2 -> b, 3 -> c, 4 -> d)

ScalaのMapのgetメソッドがある。
しかし、java.utilMapのgetとは、ちょっとちがう。
Optionというオブジェクトにつつまれた状態で、値を取得する。

scala> map.get(3)
res25: Option[java.lang.String] = Some(c)

さらに、Optionオブジェクトからgetすると中身がとりだせる。

scala> map.get(3).get
res27: java.lang.String = c


java.util.Mapのgetのように、そのままの値を取り出すためには、()を使う。デフォルト値を指定できるgetもある。

scala> map(2)
res13: java.lang.String = b

scala> map.getOrElse(3, "z")
res10: java.lang.String = c

scala> map.getOrElse(5, "z")
res11: java.lang.String = z

Scalaの流儀としては、getをつかって、Option型でとりだすのが良いお作法のらしい。

また、java.util.Mapは、java.util.Iterableを継承してなかったけれど、
ScalaのMapは、scala.collection.Iterableを継承しているので、イテレートもばっちり

scala> map.foreach {println}
(1,a)
(2,b)
(3,c)

Javaだと、Mapのままじゃだめで、entrySetメソッドで、Map.EntryのSetに変換して、イテレートさせてた。

import java.util.HashMap;
import java.util.Map;

public class LoopExample {

    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<Integer, String>();
        map.put(1, "a");
        map.put(2, "b");
        map.put(3, "c");
        for (Map.Entry<Integer, String> e : map.entrySet()) {
            Integer key = e.getKey();
            String value = e.getValue();
        }

    }
}

ふう、Javaだと、こういう小さいサンプルについては、特に、めんどうくささを感じる。

scala.collection.mutable.HashMap

ScalaのMapのように、新しいMapを生成するのでなくて、java.util.Mapのように、自分自身の中身を変化させるMapが使いたい場合は、
http://www.scala-lang.org/api/current/scala/collection/mutable/HashMap
がある。