Udostępnij za pośrednictwem


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 の新機能についてご紹介したいと思います。