マップ 同期集合と同期マップ 目次
最新版は Scala Documentation に移行しました。

同期集合と同期マップ

SynchronizedMap トレイトを好みのマップ実装にミックスインすることでスレッドセーフな可変マップを得ることができる。例えば、以下のコードが示すように、HashMapSynchronizedMap をミックスインすることができる。この例は MapSynchronizedMap の二つのトレイト、そして HashMap という一つのクラスを scala.collection.mutable パッケージからインポートすることから始まる。例の残りは makeMap というメソッドを宣言するシングルトンオブジェクト MapMaker を定義する。makeMap メソッドは戻り値の型を文字列をキーとして文字列を値とする可変マップだと宣言する。

  import scala.collection.mutable.{Map,
      SynchronizedMapHashMap}
  object MapMaker {
    def makeMap: Map[String, String] = {
        new HashMap[String, String] with
            SynchronizedMap[String, String] {
          override def default(key: String) =
            "Why do you want to know?"
        }
    }
  }
SynchronizedMap トレイトをミックスインする。
 

makeMap 本文の第一ステートメントは SynchronizedMap トレイトをミックスインする新しい可変 HashMap を作成する。

new HashMap[String, String] with
  SynchronizedMap[String, String]

このコードを与えられると、Scala コンパイラは SynchronizedMap をミックスインする HashMap の合成的な子クラスを生成し、そのインスタンスを作成する (そして、それを戻り値として返す)。この合成クラスは、以下のコードのため、default という名前のメソッドをオーバーライドする。

override def default(key: String) =
  "何故知りたい?"

通常は、ある特定のキーに対する値をマップに問い合わせて、そのキーからの写像が無い場合はNoSuchElementException が発生する。新たなマップのクラスを定義して default メソッドをオーバーライドした場合は、しかしながら、存在しないキーに対する問い合わせに対して、この新しいマップは default が返す値を返す。そのため、同期マップのコードでコンパイラに生成された HashMap の合成の子クラスは、存在しないキーに対する問い合わせに "何故知りたい?" と少々意地の悪い答えを返す。

makeMap メソッドが返す可変マップは SynchronizedMap トレイトをミックスインするため、複数のスレッドから同時に使うことができる。マップへのそれぞれのアクセスは同期化される。以下は、インタープリタ中で一つのスレッドから使用した例だ:

scala> val capital = MapMaker.makeMap  
capital: scala.collection.mutable.Map[String,String] = Map()
scala> capital ++ List("US" -> "Washington",
            "Paris" -> "France""Japan" -> "Tokyo")
res0: scala.collection.mutable.Map[String,String] =
  Map(Paris -> France, US -> Washington, Japan -> Tokyo)
scala> capital("Japan")
res1: String = Tokyo
scala> capital("New Zealand")
res2: String = 何故知りたい?
scala> capital += ("New Zealand" -> "Wellington")
scala> capital("New Zealand")                    
res3: String = Wellington

同期集合も同期マップと同じ要領で作成することができる。例えば、このように SynchronizedSet トレイトをミックスインすることで同期 HashSet を作ることができる:

import scala.collection.mutable
val synchroSet =
  new mutable.HashSet[Int] with
      mutable.SynchronizedSet[Int]

最後に、同期コレクションを使うことを考えているならば、java.util.concurrent の並行コレクションを使うことも考慮した方がいいだろう。

続いては、具象不変コレクションクラス


マップ 同期集合と同期マップ 目次