Freigeben über


HashSet のご紹介

皆さんこんにちは

Tech Ed DEMO フォロー第2段ということで、今回は .NET Frmework 3.5 から追加される新しい Collection である HashSet についてご紹介したいと思います。

この HashSet は重複のない要素を格納する Collection で順序性は保証されません。ここでいう重複のない要素とは、Stack 上の値の Hash 値での比較になります。つまり、 Struct の場合は保持する値が同じであれば同じ値になりますが、Class の場合インスタンスが異なれば保持する値が同じ値でも HashSet 上では異なる値になるので、注意が必要です。既存のクラスで言うと、HashTable や Dictionary のキーと同じしくみです。

下記のコードでは重複のないランダムな整数を出力するプログラムです。 Random クラスで生成した乱数は重複が存在するので、重複をチェックしていますが、※の部分で HashSet に Add するときに重複の有無が確認できます。List などではわざわざ Contains で確認してから Add することになるわけですが、その必要がなくなりました。

public static void GenerateRandList()
{    
    for (int i = 0; i < 10; i++)
    {
        int gen = GenerateNum();
        Console.WriteLine(gen);
    }
}

private static int GenerateNum()
{
    HashSet<int> record = new HashSet<int>);
    Random rand = new Random(DateTime.Now.Second);
    int gen;
    do
    {
        gen = rand.Next(10);
    } while (!record.Add(gen));//※ここで重複確認をしています。
    return gen;
}

また、Struct の場合と Class の場合の結果の違いを示すコードを書きに書いておきます。

private static void TryHashSet()
{
    //構造体(struct)の場合
    HashSet<DateTime> hsForStruct = new HashSet<DateTime>();
    long dtlong = DateTime.Now.Ticks;

    DateTime dt1 = new DateTime(dtlong);
    DateTime dt2 = new DateTime(dtlong);
    hsForStruct.Add(dt1);
    Console.WriteLine("Structで同じ値の異なるインスタンスは{0}", hsForStruct.Add(dt2))
    //クラス(class)の場合
    HashSet<Wrapper> hsForClass = new HashSet<Wrapper>();

    Wrapper wrp1 = new Wrapper() { number = 100 };
    Wrapper wrp2 = new Wrapper() { number = 100 };

    hsForClass.Add(wrp1);
    Console.WriteLine("Classで同じ値の異なるインスタンスは{0}", hsForClass.Add(wrp2));
}

//サンプルで使用しているクラス定義
class Wrapper { public long number { get; set; } };

お時間があるときにお試しください。次回は WCF の新機能についてご紹介したいと思います。