scalaプログラミング第17章学習ノート(2)——セットとマッピング

9662 ワード

デフォルトでは、「Set」または「Map」を使用すると、可変オブジェクトが取得されます.可変バージョンが必要な場合は、まず引用を明記する必要があります.
同じソース・ファイルで可変バージョンと非可変バージョンのセットまたはマッピングを使用する場合は、1つの方法として、可変バージョンを含むパッケージ名を参照します.
scala> import scala.collection.mutable

import scala.collection.mutable

従来と同様に、可変セットはSetで表すことができるが、現在はmutableでも用いることができる.Setは可変セットを指す.例を次に示します.
scala> val mutaSet = mutable.Set(1, 2, 3)

mutaSet: scala.collection.mutable.Set[Int] = Set(1, 2, 3)

セットの使用
セットの重要な特性は、使用するオブジェクトの==操作をチェックし、各オブジェクトがセット内で最大1つのコピーしか保持されていないことを確認することです.たとえば、文字列の異なる単語をセットでカウントできます.
スペースと句読点を単語の区切り記号として指定すると、Stringのsplitメソッドは文字列を単語に分割することができます.正規表現"[!,.]「この機能を完了するには十分です.文字列は、1~複数のスペースまたは句読点がある場所ごとに分割される必要があります.
scala> val text = "See Spot run. Run, Spot. Run!"

text: String = See Spot run. Run, Spot. Run!



scala> val wordsArray = text.split("[ !,.]+")

wordsArray: Array[String] = Array(See, Spot, run, Run, Spot, Run)

異なる単語をカウントするには、まず同じ大文字と小文字にしてセットに追加します.セットは繰り返し追加できないため、異なる単語はセットに1回しか表示されません.まず、Set伴生オブジェクトが提供するemptyメソッドを使用して空のセットを作成できます.
scala> val words = mutable.Set.empty[String]

words: scala.collection.mutable.Set[String] = Set()

次に、for式ですべての単語を列挙し、小文字に変換し、+=オペレータを使用して可変セットに追加します.
scala> for (word <- wordsArray)

       words += word.toLowerCase



scala> words

res2: scala.collection.mutable.Set[String] = Set(see, run, spot)

マッピングの使用
マッピングは、値をコレクション内の要素に関連付けるために使用できます.マッピングの使用は配列に近いが、0からカウントされる整数だけでなく、任意のタイプのキーを使用してインデックスを作成することができる.scalaを参照する場合collection.mutableパッケージでは、空の可変マッピングを作成することもできます.
scala> val map = mutable.Map.empty[String, Int]

map: scala.collection.mutable.Map[String,Int] = Map()

マップ内のエントリの設定は、配列内のものと似ています.
scala> map("hello") = 1



scala> map("there") = 2



scala> map

res5: scala.collection.mutable.Map[String,Int] = Map(hello -> 1, there -> 2)

 
同様に、読み出しマッピングと読み出し配列も同じです.
scala> map("hello")

res6: Int = 1

上の例を一緒にすると、文字列の単語の出現回数をカウントする方法があります.
scala> def countWords(text: String) = {

     | val counts = mutable.Map.empty[String, Int]

     | for (rawWord <- text.split("[ ,!.]+")) {

     | val word = rawWord.toLowerCase

     | val oldCount =

     | if (counts.contains(word)) counts(word)

     | else 0

     | counts += (word -> (oldCount + 1))

     | }

     | counts

     | }

countWords: (text: String)scala.collection.mutable.Map[String,Int]



scala> countWords("See Spot run! Run, Spot. Run!")

res7: scala.collection.mutable.Map[String,Int] = Map(spot -> 2, see -> 1, run ->

 3)

秩序化されたセットとマッピングscalaの集合ライブラリは、SortedSetとSortedMapの特質を提供します.これら2つの特質はそれぞれクラスTreeSetとTreeMapによって実現され,いずれも赤と黒の木を用いて要素(TreeSetクラス)またはキー(TreeMapクラス)を秩序正しく保存している.特定の順序はOrdered特質に依存し、セットの要素タイプまたはマッピングされたキータイプは混入するか、または暗黙的にOrdered特質に変換できる必要がある.これらのクラスには、可変タイプのバージョンしかありません.TreeSetの例を次に示します.
scala> import scala.collection.immutable.TreeSet

import scala.collection.immutable.TreeSet



scala> val ts = TreeSet(9, 3, 1, 8, 0, 2, 7, 4, 6, 5)

ts: scala.collection.immutable.TreeSet[Int] = TreeSet(0, 1, 2, 3, 4, 5, 6, 7, 8,

 9)



scala> val cs = TreeSet('f', 'u', 'n')

cs: scala.collection.immutable.TreeSet[Char] = TreeSet(f, n, u)

TreeMapの例を次に示します.
scala> import scala.collection.immutable.TreeMap

import scala.collection.immutable.TreeMap



scala> var tm = TreeMap(3 -> 'x', 1 -> 'x', 4 -> 'x')

tm: scala.collection.immutable.TreeMap[Int,Char] = Map(1 -> x, 3 -> x, 4 -> x)



scala> tm += (2 -> 'x')



scala> tm

res9: scala.collection.immutable.TreeMap[Int,Char] = Map(1 -> x, 2 -> x, 3 -> x,

 4 -> x)

同期(Synchronized)セットとマッピング
スレッドの安全なマッピングが必要な場合は、SynchronizedMapの特質を目的の特質クラス実装に組み込むことができます.次は、SynchronizedMapがHashMapに混入した例です.
import scala.collection.mutable.{Map, SynchronizedMap, HashMap}



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?"

    }

  }

}

マッピングを要求して特定のキーに関連付けられた値を返し、そのキーのマッピングが実際に存在しない場合は、デフォルトではNoSuchElementExceptionが得られます.しかし、新しいマッピングクラスを定義してdefaultメソッドを再ロードすると、この新しいマッピングは、存在しないキーをクエリーするときにdefaultメソッドの戻り値を返します.上のコードによると、コンパイラによって構築された合成HashMapサブクラスは、存在しないキーをクエリするときに「Why do you want to know?「.次の例では、インタプリタで単一スレッドがマッピングにアクセスする場合を示します.
scala> import scala.collection.mutable.{Map, SynchronizedMap, HashMap}

import scala.collection.mutable.{Map, SynchronizedMap, HashMap}



scala> 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?"

     |     }

     |   }

     | }

warning: there was one deprecation warning; re-run with -deprecation for details



defined object MapMaker



scala> val capital = MapMaker.makeMap

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



scala> capital ++ List("US" -> "Washington", "Paris" -> "France", "Japan" -> "To

kyo")

res10: scala.collection.mutable.Map[String,String] = Map(Paris -> France, Japan

-> Tokyo, US -> Washington)



scala> capital("Japan")

res11: String = Why do you want to know?



scala> capital += ("New Zealand" -> "Wellington")

res12: capital.type = Map(New Zealand -> Wellington)



scala> capital("New Zealand")

res13: String = Wellington

同期マッピングの作成と同様の方法で同期セットを作成できます.例えば、SynchronizedSetの特質を混入することによって、同期化されたHashSetを作成することができる.
scala> import scala.collection.mutable

import scala.collection.mutable



scala> val synchroSet =

     | new mutable.HashSet[Int] with 

     | mutable.SynchronizedSet[Int]

warning: there was one deprecation warning; re-run with -deprecation for details



synchroSet: scala.collection.mutable.HashSet[Int] with scala.collection.mutable.SynchronizedSet[Int] = Set()