具象不変コレクションクラス トップ 集合 マップ 目次
最新版は Scala Documentation に移行しました。

マップ

マップ (Map) はキーと値により構成されるペアの Iterable の一種で、写像 (mapping) や関連 (association) とも呼ばれる。Scala の Predef クラスは、ペアの (key, value)key -> value と書けるような暗黙の変換を提供する。例えば、Map("x" -> 24, "y" -> 25, "z" -> 26)Map(("x", 24), ("y", 25), ("z", 26)) と全く同じことを意味するがより可読性がある。

マップの基本的な演算は集合のものと似ている。それらは、以下の表 にまとめられており、以下のカテゴリーに分類できる:

Map トレイトの演算    
使用例 振る舞い
検索演算:
ms get k マップ ms 内のキー k に関連付けられた値のオプション値、もしくは、キーが見つからない場合、None
ms(k) (展開した場合、ms apply k) マップ ms 内のキー k に関連付けられた値、もしくは、キーが見つからない場合は例外。
ms getOrElse (k, d) マップ ms 内のキー k に関連付けられた値、もしくは、キーが見つからない場合、デフォルト値 d
ms contains k ms がキー k への写像を含むかを調べる。
ms isDefinedAt k contains に同じ。
加算と更新演算:
ms + (k -> v) ms 内の全ての写像と、キー k から値 v への写像 k -> v を含むマップ。
ms + (k -> v, l -> w) ms 内の全ての写像と、渡されたキーと値のペアを含むマップ。
ms ++ kvs ms 内の全ての写像と、kvs内の全てのキーと値のペアを含むマップ。
ms updated (k, v) ms + (k -> v) に同じ。
減算:
ms - k キー k からの写像を除く、ms 内の全ての写像。
ms - (k, l, m) 渡されたキーからの写像を除く、ms 内の全ての写像。
ms -- ks ks内のキーからの写像を除く、ms 内の全ての写像。
サブコレクション取得演算:
ms.keys ms内の全てのキーを含む iterable。
ms.keySet ms内の全てのキーを含む集合。
ms.keysIterator ms内の全てのキーを返すイテレータ。
ms.values ms内のキーに関連付けられた全ての値を含む iterable。
ms.valuesIterator ms内のキーに関連付けられた全ての値を返すイテレータ。
変換演算:
ms filterKeys p キーが条件関数 p を満たす ms内の写像のみを含むマップのビュー。
ms mapValues f ms内のキーに関連付けられた全ての値に関数 f を適用して得られるマップのビュー。

可変マップ (mutable.Map) は他にも以下の表にまとめた演算をサポートする。

mutable.Map トレイトの演算  
使用例 振る舞い
加算と更新演算:
ms(k) = v (展開した場合、ms.update(x, v))。マップ ms に副作用としてキー k から値 v への写像を加え、既に k からの写像がある場合は上書きする。
ms += (k -> v) マップ ms に副作用としてキー k から値 v への写像を加え、ms自身を返す。
ms += (k -> v, l -> w) マップ ms に副作用として渡された写像を加え、ms自身を返す 。
ms ++= kvs マップ ms に副作用として kvs内の全ての写像を加え、ms自身を返す。
ms put (k, v) マップ ms にキー k から値 v への写像を加え、以前の k からの写像のオプション値を返す。
ms getOrElseUpdate (k, d) マップ ms内にキー k が定義されている場合は、関連付けられた値を返す。定義されていない場合は、ms に写像 k -> d を加え、d を返す。
減算:
ms -= k マップ ms から副作用としてキー k からの写像を削除して、ms自身を返す。
ms -= (k, l, m) マップ ms から副作用として渡されたキーからの写像を削除して、ms自身を返す。
ms --= ks マップ ms から副作用として ks内の全てのキーからの写像を削除して、ms自身を返す。
ms remove k マップ ms からキー k からの写像を削除して、以前の k からの写像のオプション値を返す。
ms retain p ms内の写像でキーが条件関数 p を満たすものだけを残す。
ms.clear() ms から全ての写像を削除する。
変換演算:
ms transform f マップ ms内の全ての関連付けされた値を関数 f を使って変換する。
クローン演算:
ms.clone ms と同じ写像を持つ新しい可変マップを返す。

マップの加算と減算は、集合のそれにならう。集合と同様、非破壊的な演算である +, -, と updated を提供するが、加算マップをコピーする必要があるため、これらはあまり使われることがない。そのかわり、可変マップは通常 m(key) = valuem += (key -> value) という二種類の更新演算を使って上書き更新される。さらに前に key から関連付けされていた値を Option値で返すか、マップに key が無ければ None を返すというバリアントである m put (key, value) もある。

getOrElseUpdate はキャッシュとして振る舞うマップにアクセスするのに役立つ。例えば、関数 f により呼び出される時間のかかる計算があるとする:

scala> def f(x: String) = { 
       println("taking my time."); sleep(100)
       x.reverse }
f: (x: String)String

さらに、f には副作用を伴わず、同じ引数で何回呼び出しても同じ戻り値が返ってくると仮定する。この場合、引数と以前の f 計算結果の対応関係をマップに格納して、引数がマップに無いときだけ f の結果を計算すれば時間を節約できる。この時、マップは関数 f の計算のキャッシュであると言える。

val cache = collection.mutable.Map[String, String]()
cache: scala.collection.mutable.Map[String,String] = Map()

これにより、より効率的な、キャッシュするバージョンの関数 f を作成することができる。

scala> def cachedF(s: String) = cache.getOrElseUpdate(s, f(s))
cachedF: (s: String)String
scala> cachedF("abc")
taking my time.
res3: String = cba
scala> cachedF("abc")
res4: String = cba

getOrElseUpdate の第二引数は「名前渡し」(by-name) であるため、上の f("abc")getOrElseUpdate が必要とする場合、つまり第一引数が cache に無い場合においてのみ計算されることに注意してほしい。 cachedF をより率直に、普通の map 演算を用いて実装することもできるが、コードは少し長くなる:

def cachedF(arg: String) = cache get arg match {
  case Some(result) => result
  case None => 
    val result = f(x)
    cache(arg) = result
    result
}

続いては、


具象不変コレクションクラス トップ 集合 マップ 目次