書籍転載
文法からはじめるプログラミング言語Microsoft Visual Basic入門

VB開発者のためのコレクション・クラス入門
― 第12章 クラスライブラリの活用 ―

WINGSプロジェクト 高江 賢(監修 山田 祥寛)
2010/09/08
Page1 Page2 Page3

12.1.6 Dictionaryクラス

 ハッシュテーブルは、以前のバージョンではHashtableクラスとして提供されていましたが、ジェネリックコレクションクラスではDictionaryクラスになりました。

 ハッシュテーブルとは、キー(key)と値(value)のペアでデータを保持しているコレクションです。基本的な配列では数値のインデックスで要素にアクセスしますが、ハッシュテーブルでは数値以外のデータ型のキーで値にアクセスすることもできます。このようなインデックスを使用できる配列のことを、連想配列と呼びます。ハッシュテーブルとは、連想配列を実装したデータ構造の1つです。たとえば、7.2.3項で示したハッシュテーブルのサンプルコード「indexer2.vb」では、英語の曜日(Mon、Tue)をキーとして、日本語の曜日(月、火)を格納していました。

図12-7 ハッシュテーブル

 次に、文字列をキー、クラスを値とするハッシュテーブル(Dictionaryクラス)を操作するサンプルコードを示します。

Class MainClass
  Private Class Medal

    Dim gold As Integer
    Dim silver As Integer
    Dim bronze As Integer

    ' コンストラクタ
    Public Sub New(ByVal g As Integer, ByVal s As Integer, _
             ByVal b As Integer)
      gold = g
      silver = s
      bronze = b
    End Sub

    ' フィールドの値を出力
    Public Sub output()
      Console.WriteLine("金:{0}, 銀:{1}, 銅:{2}", gold, silver, _
                              bronze)
    End Sub
  End Class

  Public Shared Sub Main()

    ' 1:キーを文字列、値をMedalクラスとしてインスタンス化
    Dim win = New Dictionary(Of String, Medal)

    ' 2:要素を追加
    win("Japan") = New Medal(20, 10, 8)
    win("China") = New Medal(10, 5, 30)
    win.Add("USA", New Medal(15, 10, 2))

    ' 3:"USA"がキーのMedalクラスを取得して出力
    Dim m = win("USA")
    m.output()

    Try
      ' 4:"Russia"をキーとして値を取得しようとすると
      m = win("Russia")
      m.output()

    Catch e As Exception
      ' "Russia"はキーにないので例外が発生
      Console.WriteLine(e.Message)
    End Try

    ' 5:"China"がキーのMedalクラスを取得して出力
    win.TryGetValue("China", m)
    m.output()

    ' 6:"中国"はキーにないので
    '    mは参照型の既定値であるNothingとなる
    win.TryGetValue("中国", m)
    Console.WriteLine(m Is Nothing)

    ' 7:キーが存在するかどうかを確認
    If win.ContainsKey("Japan") Then
      Console.WriteLine("存在")
    End If

    ' 8:値があるかどうかの確認
    win.TryGetValue("USA", m)
    If win.ContainsValue(m) Then
      Console.WriteLine("値あり")
    End If

    ' 9:キーと値を列挙
    For Each kp As KeyValuePair(Of String, Medal) In win
      Console.Write("{0}  ", kp.Key)
      kp.Value.output()
    Next

  End Sub
End Class
[サンプル]dict.vb

金:15, 銀:10, 銅:2
指定されたキーはディレクトリ内に存在しませんでした。
金:10, 銀:5, 銅:30
True
存在
値あり
Japan 金:20, 銀:10, 銅:8
China 金:10, 銀:5, 銅:30
USA 金:15, 銀:10, 銅:2

 少し長いコードなので、コメントに番号を付けてあります。以降の説明に示している番号が、それぞれに対応します。

 Medalクラスは、3つのInteger型のフィールドを持つクラスです。コンストラクタで受け取った値がフィールドに設定されます。フィールドの値を「金:<goldの値>、銀:<silverの値>、銅:<bronzeの値>」の形式で出力するoutputメソッドも定義してあります。

 Mainメソッドでは、文字列をキーとしてMedelクラスを値とするDictionaryクラスをインスタンス化しています(1)。Dictionaryに要素を追加するには、インデクサの()を使用するか、Addメソッドを使用します(2)。指定したキーがまだなければ、新しい要素として登録されます。キーが既に存在する場合は、()による追加では指定した新しい値に置き換えられ、Addメソッドでは例外が発生します。

 キーの値を取得するには、「インスタンス名(キー)」という形式でキーを指定します(3)。この場合、指定したキーが存在しないと例外が発生します(4)。これを防ぐには、TryGetValueメソッドを使用します。TryGetValueメソッドでは、キーがある場合は対応する値が返され(5)、キーがない場合は値が参照型の既定値であるNothingに初期化されて返されます(6)。

 また、ContainsKeyメソッドではキーが存在するかどうかを確認でき(7)、ContainsValueメソッドでは値が存在するかどうかを確認できます(8)。

 For Eachループでキーと値を列挙することもできます。キーと値を同時に取得または設定する場合は、KeyValuePair構造体を用います(9)。この構造体はAddメソッドのパラメータとして指定することもできます。

 Dictionaryクラスの他の主なメソッドについては、先ほどの表を参照してください。

12.1.7 SortedListクラスとSortedDictionaryクラス

 SortedListクラスは、キーによって自動的に並べ替えられるコレクションです。データ構造は配列をベースにしています。一方、SortedDictionaryクラスは、バイナリサーチツリーと呼ばれるデータ構造です。

 ツリー構造とは、木が枝をのばすような構造のことです。ツリーの中でも、あるノードが持つ枝の数が2つ以下であるものをバイナリツリーと呼びます。また、バイナリツリーの中で、データの大小によってノードの位置を決めるツリーをバイナリサーチツリーと呼びます。

 ここでは、この2つのクラスの使い方を簡単に紹介します。詳しくはMSDNライブラリのSortedListクラスおよびSortedDictionaryジェネリッククラスの解説を参照してください。

図12-8 バイナリサーチツリー

 どちらのクラスもDictionaryクラスと同様、要素はキーと値のペアになりますが、要素はキーの順番によって並べ替えられて格納されます。そのため、キーとインデックスのどちらを使ってアクセスすることも可能です。2つのクラスの違いは、ListクラスとLinkedListクラスとの違いに似ています。主な相違点は次のとおりです。

  • SortedListクラスの方が、メモリ使用量が少ない
  • SortedDictionaryクラスの方が、挿入および削除が高速
  • すべての要素を一度に取り出す場合は、SortedListクラスの方が高速

 どちらのクラスも、メソッドはDictionaryクラスとほとんど同じです。先ほどのサンプルコードで、クラス名を入れ替えるだけで実行することができます。つまり、最初のインスタンス化の部分を次のように変更するだけです。

Dim win = New SortedDictionary(Of String, Medal)
Dim win = New SortedList(Of String, Medal)

 この3つのクラスによる実行結果は、最後のFor Echループによる列挙のみ異なります。SortedListクラスとSortedDictionaryクラスでは、要素を追加した際に、次のようにキーがアルファベット順に並べ替えられています。

China 金:10, 銀:5, 銅:30
Japan 金:20, 銀:10, 銅:8
USA 金:15, 銀:10, 銅:2

 既定では単純にキーが比較されて並べ替えられますが、並べ替える処理をユーザーが実装することもできます。その場合、キーを比較するComparerメソッドが宣言されているIComparerインターフェイスというインターフェイスを実装して、SortedDictionaryクラスまたはSortedListクラスのコンストラクタで指定します。

 Comparerメソッドは、Object型のパラメータ2つの、Integer型の値を返す関数です。引数を比較して、1つ目の引数が2つ目の引数より小さければ負の値、おなじなら0、大きければ正の値を返すように実装します。

 次のサンプルコードは、キーの降順に要素を格納するSortedListクラスの例です。

Class MainClass

  ' 独自の比較処理
  Public Class myReverserClass : Implements IComparer

    Private Function Compare(ByVal x As Object, ByVal y As Object) _
      As Integer Implements IComparer.Compare

      ' パラメータを逆にして比較した結果を返す
      Return ((New CaseInsensitiveComparer()).Compare(y, x))

    End Function

  End Class

  Public Shared Sub Main()

    ' SortedListに独自の比較処理を組み込む
    Dim myList = New SortedList(New myReverserClass())

    myList.Add("1st", "Tigers")
    myList.Add("2nd", "Giants")
    myList.Add("3rd", "Dragons")

    For i As Integer = 0 To myList.Count - 1

      ' キーと値を表示
      Console.WriteLine("[{0}]{1}", myList.GetKey(i), _
                myList.GetByIndex(i))

    Next

  End Sub
End Class
[サンプル]mylist.vb

[3rd]Dragons
[2nd]Giants
[1st]Tigers

 この例では、2つのオブジェクトが等しいかどうかを比較するCaseInsensitiveComparerクラスを利用しています。このクラスも、IComparerインターフェイスを実装したクラスで、Compareメソッドでは、文字列の大文字と小文字とを区別しないで比較します。このメソッドのパラメータに指定する値を逆にすることで、降順を実現しています。

 この後に、「12.2 文字列処理」「12.3 日付と時刻の表示」「12.4 ファイルへの入出力」「12.5 LINQ(Visual Basic 2008)」が続きますが、今回の転載では割愛します。次回は、「第8章 ポリモーフィズム〜クラスの操作方法」を転載する予定です。End of Article

 

 INDEX
  [書籍転載]文法からはじめるプログラミング言語Microsoft Visual Basic入門
  VB開発者のためのコレクション・クラス入門
    1.リスト、スタック、キュー/VB 2003までのコレクションクラス
    2.ジェネリック/LinkedListクラス/StackとQueueクラス
  3.Dictionaryクラス/SortedListクラスとSortedDictionaryクラス

インデックス・ページヘ 「文法からはじめるプログラミング言語Microsoft Visual Basic入門」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間