HashSet <T>とList <T>の違いは何ですか?


156

HashSet<T>List<T>.NETの違いは何ですか?

多分あなたはどのケースHashSet<T>が好まれるべきかを例で説明できList<T>ますか?


22
トピックに関するいくつかの読み物:C#/。NETの基礎:適切なコレクションクラスの選択
FredrikMörkJun

en.wikipedia.org/wiki/Hash_tableおよびen.wikipedia.org/wiki/Dynamic_arrayの Wikipediaの記事を参照することをお勧めします。
mqp

関連のパフォーマンスについては、HashSetの-VS-リストパフォーマンス
nawfal

回答:


213

リストとは異なり<> ...

  1. HashSetは、重複するメンバーのないリストです。

  2. HashSetは一意のエントリのみを含むように制限されているため、内部構造は検索用に最適化されています(リストと比較して)-かなり高速です

  3. HashSetへの追加はブール値を返します-Setに既に存在するために追加が失敗した場合はfalse

  4. セットに対して数学的なセット操作を実行できます:Union / Intersection / IsSubsetOfなど。

  5. HashSetはICollectionのみを実装していないICollection

  6. HashSetではインデックスを使用できません。列挙子のみを使用できます。

HashSetを使用する主な理由は、Set操作の実行に関心がある場合です。

与えられた2つのセット:hashSet1とhashSet2

 //returns a list of distinct items in both sets
 HashSet set3 = set1.Union( set2 );

LINQを使用する同等の操作と比較して飛ぶ。書くのもすっきり!


IDK、私はUnion方法に問題がありました。UnionWith代わりに使っていました。
ユーザー

2
+1「HashedSetを使用する主な理由は、Set操作の実行に関心がある場合です。」
LCJ 2012年

12
実際には、コレクションを「バッグアイテム」として扱うことができる場合にはHashSetsが適していると指摘する答えが好きです。セット操作は、包含チェックほど頻繁ではありません。一意のアイテム(コードなど)のセットがあり、包含を確認する必要がある場合はいつでも、HashSetが便利です。
ThunderGr 2013年

いい答えだ。パフォーマンス特性の違いもいくつか追加したくなります。
nawfal 2014年

1
質問:主な理由は、重複するアイテムがないことの確実性がないことですか?
Andrea Scarafoni

54

より正確には、例を使って説明しましょう。

次の例のようにHashSetを使用することはできません。

HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
for (int i = 0; i < hashSet1.Count; i++)
    Console.WriteLine(hashSet1[i]);

hashSet1[i] エラーが発生します:

タイプ[System.Collections.Generic.HashSet]の式に[]を使用したインデックス作成を適用できません

foreachステートメントを使用できます。

foreach (var item in hashSet1)
    Console.WriteLine(item);

重複するアイテムをHashSetに追加することはできませんが、Listでこれを行うことができます。また、HashSetにアイテムを追加しているときに、アイテムが含まれているかどうかを確認できます。

HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
if (hashSet1.Add("1"))
   Console.WriteLine("'1' is successfully added to hashSet1!");
else
   Console.WriteLine("'1' could not be added to hashSet1, because it contains '1'");

HashSetのは、のようないくつかの便利な機能があるIntersectWithUnionWithIsProperSubsetOfExceptWithSymmetricExceptWithなど

IsProperSubsetOf

HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
HashSet<string> hashSet3 = new HashSet<string>() { "1", "2", "3", "4", "5" };
if (hashSet1.IsProperSubsetOf(hashSet3))
    Console.WriteLine("hashSet3 contains all elements of hashSet1.");
if (!hashSet1.IsProperSubsetOf(hashSet2))
    Console.WriteLine("hashSet2 does not contains all elements of hashSet1.");

UnionWith

HashSet<string> hashSet1 = new HashSet<string>() { "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
hashSet1.UnionWith(hashSet2); //hashSet1 -> 3, 2, 4, 6, 8

IntersectWith

HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" }
hashSet1.IntersectWith(hashSet2);//hashSet1 -> 4, 8

ExceptWith

 HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
 HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
 hashSet1.ExceptWith(hashSet2);//hashSet1 -> 5, 6

SymmetricExceptWith

 HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
 HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
 hashSet1.SymmetricExceptWith(hashSet2);//hashSet1 -> 4, 5, 6

ちなみに、順序はHashSetsでは保持されません。この例では、最後に要素「2」を追加しましたが、2番目の順序になっています。

HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
hashSet1.Add("1");    // 3, 4, 8, 1
hashSet1.Remove("4"); // 3, 8, 1
hashSet1.Add("2");    // 3, 2 ,8, 1

51

A HashSet<T>は、O(1)包含のルックアップを提供するように設計されたクラスです(つまり、このコレクションには特定のオブジェクトが含まれており、すぐに答えを教えてください)。

A List<T>は、O(1)動的に成長できる(動的配列と考える)よりもランダムなアクセスのコレクションを提供するように設計されたクラスです。O(n)時間内に包含をテストできます(リストがソートされていない限り、O(log n)時間内にバイナリ検索を実行できます)。

多分あなたはどのケースHashSet<T>が好まれるべきかについての例で説明することができますList<T>

で封じ込めをテストする場合O(1)


ただし、リストがソートされている場合はO(log n)です。結局のところ、ソートされていないリストを検索するよりも高速です。
Andrei

20

次のList<T>場合にaを使用します。

  • アイテムのコレクションを特定の順序で保存します。

(アイテム自体の値ではなく)必要なアイテムのインデックスがわかっている場合、取得はO(1)です。インデックスがわからない場合O(n)は、ソートされていないコレクションの場合、アイテムの検索に時間がかかります。

次のHashset<T>場合にaを使用します。

  • 特定のオブジェクトがコレクションに含まれているかどうかをすばやく確認します。

検索したいものの名前がわかっている場合、LookupはO(1)(「ハッシュ」の部分です)。のような順序付けは維持されずList<T>、重複を保存することもできません(重複を追加しても効果はありません。それが「セット」部分です)。

Hashset<T>スクラブルのゲームでプレイされた単語が英語(または他の言語)で有効な単語であるかどうかを確認したい場合などに、aを使用する場合の例を示します。そのようなゲームのオンラインバージョンのすべてのインスタンスで使用されるWebサービスを構築したい場合は、さらに良いでしょう。

A List<T>は、プレーヤーのスコアを追跡するスコアボードを作成するのに適したデータ構造です。


15

リストは順序付きリストです。です

  • 整数インデックスでアクセス
  • 重複を含めることができます
  • 予測可能な順序があります

HashSetはセットです。それ:

  • 重複するアイテムをブロックできます(Add(T)を参照)
  • セット内の商品の順番を保証するものではありません
  • IntersectWith、IsProperSubsetOf、UnionWith など、セットに対して期待する操作があります。

リストは、アイテムに追加、挿入、および削除できる配列のようなものであるかのように、コレクションにアクセスする場合に適しています。順序が重要ではないアイテムの「バッグ」のようにコレクションを扱いたい場合、またはIntersectWithやUnionWithなどの操作を使用して他のセットと比較したい場合、HashSetがより良い選択です。


3

リストは必ずしも一意ではありませんが、ハッシュセットは一意です。


3

リストは、配列とは異なり、エントリを追加および削除できるタイプTのオブジェクトの順序付けられたコレクションです。

メンバーを格納した順序でメンバーを参照し、アイテム自体ではなく位置でメンバーにアクセスするリストを使用します。

HashSetはディクショナリのようなもので、アイテム自体がキーであると同時に値でもあり、順序は保証されません。

オブジェクトがコレクション内にあることを確認したい場合はHashSetを使用します


1
明確にするために、誰かが一目で間違ってそれを読んだ場合- List順序は維持されます(つまり、物事が追加されたとき)が、アイテムを自動的に並べ替えることはしません。を呼び出す.Sortか使用する必要がありSortedListます。
drzaus 2013年

1

これらのデータ構造をデータ駆動型開発での実際の使用に適用する場合、HashSetは、データのクレンジングと移行のために、データアダプターソースに対するレプリケーションのテストに非常に役立ちます。

また、DataAnnotationsクラスを使用する場合は、クラスプロパティにキーロジックを実装し、HashSetを使用して(クラスター化されているかどうかにかかわらず)Naturalインデックスを効果的に制御できます。これは、List実装では非常に困難です。

リストを使用する強力なオプションは、DropDownListヘルパーのMVCビューにクラスのリストを送信したり、WebApiを介してJSON構成として送信したりするなど、ビューモデルの複数のメディアにジェネリックを実装することです。このリストにより、典型的なクラスコレクションロジックが可能になり、さまざまな媒体に対する単一のビューモデルを計算するためのより「インターフェース」のようなアプローチの柔軟性が維持されます。

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