不変なコレクションの具象クラストップSetsマップ目次

マップ

マップ(Map)はキーと値のペアからなるIterableです(写像関連付けとも言います)。 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 msの全ての関連付けからキーkに対する関連付けを除いたマップ。
ms - (k, l, m) msの全ての関連付けから与えられたキーに対する関連付けを除いたマップ。
ms -- ks msの全ての関連付けからks内の任意のキーに対する関連付けを除いたマップ。
部分コレクション:
ms.keys ms内の各キーを含むイテラブル。
ms.keySet ms内の各キーを含む集合。
ms.keysIterator ms内の各キーを返すイテレータ。
ms.values ms内でキーと関連付けられた各値を含むイテラブル。
ms.valuesIterator ms内でキーと関連付けられた各値を返すイテレータ。
変換:
ms filterKeys p ms内の関連付けでキーが述語pを満たすもののみを含むマップのビュー(訳註: ここで言うビューとは後で説明するビューとは異なり、フィルタリングのみを遅延的に評価し、その他の演算は遅延的に扱わない。mapValuesも同様)。
ms mapValues f ms内のキーに関連付けられた各値に関数fを適用してできたマップのビュー。

可変なマップはさらに以下の表に要約できるメソッドを提供します。

クラス 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 マップmskvsの全ての関連付けを副作用として追加し、ms自身を返す。
ms put (k, v) マップmsにキーkから値vへの関連付けを副作用として追加し、以前kと関連付けられていた値をオプション値として返す。
ms getOrElseUpdate (k, d) もしキーkがマップmsで定義されていれば、その関連付けられた値を返す。 そうでなければ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は通常m(key) = valuem += (key -> value)といった2つの変種により「直接」変更されます。 m put (key, value)という変種もあり、keyに以前関連付けられていた値を含むOptionか、もし以前マップにkeyが存在しなければNoneを返します。

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の第2引数は「名前呼び」であり、f("abc")の計算はgetOrElseUpdateがその第2引数の値を必要とする場合、正確には最初の引数がマップcacheに無い場合にのみ実行される点に注意してください。 cachedFは直接基本的なマップ演算のみを使って実装できますが、より多くのコードが必要です:

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

続いては:


不変なコレクションの具象クラストップSetsマップ目次