定義:HashSetとは何ですか?


420

HashSet C#HashSetデータ構造は、.NET Framework 3.5で導入されました。実装されているメンバーの完全なリストは、HashSet MSDNページにあります。

  1. どこで使用されていますか?
  2. なぜそれを使いたいのですか?



内部ではハッシュテーブルを使用します。優れたハッシュテーブル実装(たとえば、Dictionary <T>)がある場合は、HashSetを自分で簡単に実装できます。
Raz Megrelidze 2015

回答:


614
    1. Aは、HashSetオブジェクトのセットを保持しているが、方法で、それはあなたが簡単かつ迅速にオブジェクトがすでにセットであるかどうかを判断することを可能にすること。これは、配列を内部的に管理し、オブジェクトのハッシュコードから計算されたインデックスを使用してオブジェクトを格納することによって行われます。ここを見てください

    2. HashSet一意の要素を含む順不同のコレクションです。標準のコレクション操作Add、Remove、Containsがありますが、ハッシュベースの実装を使用しているため、これらの操作はO(1)です。(たとえば、リスト(ContainsとRemoveのO(n)とは対照的です)HashSetとは異なります。)は、unionintersectionsymmetric differenceなどの標準のセット操作も提供します。ここを見てください

  1. セットにはさまざまな実装があります。いくつかは、要素をハッシュすることによって挿入と検索操作を超高速にします。ただし、これは、要素が追加された順序が失われることを意味します。他の実装では、実行時間が長くなる代わりに、追加された順序が保持されます。

HashSetC#のクラスは最初のアプローチに使用されるため、要素の順序は保持されません。通常よりはるかに高速ですList。いくつかの基本的なベンチマークは、プライマリタイプ(int、double、boolなど)を処理するときにHashSetがかなり高速であることを示しました。クラスオブジェクトを操作する場合は、はるかに高速です。つまり、HashSetは高速です。

唯一の欠点はHashSet、インデックスによるアクセスがないことです。要素にアクセスするには、列挙子を使用するか、組み込み関数を使用してHashSetをに変換し、Listそれを繰り返します。ここを見てください


13
ハッシュセットと類似のものの2つは、C#ではなく.NETです。また、HashSetは順序を保持しません。ハッシュセットから項目を追加したり削除してみてください、あなたは...に後で繰り返す場合は知っているだろう
nawfal

13

A HashSetには内部構造(ハッシュ)があり、アイテムをすばやく検索して識別できます。欠点は、HashSet(またはインデックスによる項目の取得)がかなり遅いことです。

では、なぜエントリがセットに既に存在するかどうかを誰かが知りたいのでしょうか?

a HashSetが役立つ1つの状況は、重複が存在する可能性があるリストから個別の値を取得する場合です。アイテムがアイテムに追加されるHashSetと、アイテムが存在するかどうかをすばやく判断できます(Contains演算子)。

他の利点は、HashSetSet操作です: IntersectWithIsSubsetOfIsSupersetOfOverlapsSymmetricExceptWithUnionWith

オブジェクト制約言語に精通している場合は、これらの集合演算を特定します。また、実行可能なUMLの実装に一歩近づいていることもわかります。


20
Re:マイナス面。いいえ、HashSetの反復処理は完全に高速です。第二に、インデックスでアイテムを取得することはできません。実際、要素は順不同で保存されます。
Nigel Touch

@ナイジェルタッチ。インデックス(インデックスが追加された順序)を気にしない場合、反復は高速です。ただし、インデックスが心配な場合は、インデックスをハッシュキーごとに格納する必要があります。正しいアイテムを取得するためにリストを徹底的に検索する必要があるため、かなり遅くなる可能性があります。この動作は、アイテムが追加された順序で項目にインデックスが付けられるリストとは大きく異なります。
k rey

2つのハッシュが同じではないので、なぜ高速であるかは理にかなっています。クエリが「短絡」アプローチを利用できるようにし、特定の基準をすばやく除外します。
Chef_Code 2016

8

簡単に言うと、キッチンの秘密を明かす ことはありません。一般に、セットは、重複する要素を含まないコレクションであり、その要素には特定の順序はありません。したがって、A HashSet<T>はgeneric List<T>に似ていますが、順序を失うことを犠牲にして(名前が示すようにハッシュテーブルを介して)高速ルックアップ用に最適化されています。


1
しかし、HashSet <T>が同じデータを持つ2つのオブジェクトを格納することはできますか?たとえば、それぞれが同じ内容で同じプロパティを持つ2つのProductクラスのようにできますか?
ヨハンヘルスタット

私たちは決して知ることはないと思います
デニー

@JohanHerstadクラスのEqualityComparerがそれらのプロパティを気にするか、またはそれらのプロパティを気にするIEqualityComparerでHashSetを構築すると仮定すると、なぜそうならないかわかりません。HashSetドキュメントでは、一意性を判断するためにどちらかに依存していることが明確になっています。
ベーコンビット

2

アプリケーションの観点から見ると、重複を避けるだけHashSetでよい場合は、Lookup、InsertおよびRemoveの複雑度がO(1)であるので、定数です。これが何を意味するかは、要素の数に関係HashSetなく、そのような要素があるかどうかを確認するのに同じ時間かかります。さらに、O(1)に要素を挿入しているので、この種のものに最適です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.