HashSet<T>クラス

HashSet<T>は、値を持たないDictionary<TKey,TValue>に近いです。Remarks - HashSet<T> Class (System.Collections.Generic) | Microsoft Learn

実装しているインターフェイス

[System.Serializable]
public class HashSet<T> :
    System.Collections.Generic.ICollection<T>,
    System.Collections.Generic.IEnumerable<T>,
    System.Collections.Generic.IReadOnlyCollection<T>,
    System.Collections.Generic.ISet<T>,
    System.Runtime.Serialization.IDeserializationCallback,
    System.Runtime.Serialization.ISerializable

コンストラクタ

コンストラクタ  
HashSet<T>()  
HashSet<T>(IEnumerable<T>)  
HashSet<T>(IEnumerable<T>, IEqualityComparer<T>)  
HashSet<T>(IEqualityComparer<T>)  
HashSet<T>(Int32)  
HashSet<T>(Int32, IEqualityComparer<T>)  
HashSet<T>(SerializationInfo, StreamingContext)  

HashSet<T>(IEqualityComparer<T>)

比較方法をIEqualityComparer<T>で指定することで、重複と見なす基準を変更できます。

HashSet<string> h1 = new HashSet<string>();
HashSet<string> h2 = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

IEqualityComparer<string> c1 = h1.Comparer; // System.Collections.Generic.GenericEqualityComparer<string>
IEqualityComparer<string> c2 = h2.Comparer; // System.OrdinalComparer

bool a1 = h1.Add("aa");      // true
bool a2 = h1.Add("AA");      // true
bool a3 = h2.Contains("aA"); // false

bool b1 = h2.Add("aa");      // true
bool b2 = h2.Add("AA");      // false (重複と判断され、追加されない)
bool b3 = h2.Contains("aA"); // true (一致と判断される)

HashSet<T>(Int32)

public HashSet (int capacity);
HashSet<T>(Int32) - HashSet<T> Constructor (System.Collections.Generic) | Microsoft Learn

サイズ変更は再ハッシュが必要なことにより比較的高価なため、可能ならば初期容量を指定します。このオーバーロードは.NET Framework 4.7.2以降で使用可能です。

プロパティ

プロパティ 内容
IEqualityComparer<T> Comparer セット内の値の同等を決定するのに使用されるIEqualityComparer<T>を得られる
int Count セット内の要素の数
プロパティ - HashSet<T> クラス (System.Collections.Generic) | Microsoft Learn

メソッド

メソッド 機能
TryGetValue(T, T) 指定の値を検索し、その値を得られる
Add(T) 指定の要素を追加できる
Remove(T) 指定の要素を削除できる
RemoveWhere(Predicate<T>) 指定の述語 (predicate) で定義された条件に一致する、すべての要素を削除できる
Clear() すべての要素を削除できる
Contains(T) 指定の要素が格納されているか判断できる
CopyTo(T[]) すべての要素を配列にコピーできる
   
集合演算
メソッド 機能 数学的な意味
UnionWith(IEnumerable<T>) 指定のコレクションとマージできる 和集合 (union) または加算 (addition)
IntersectWith(IEnumerable<T>) 指定のコレクションにない要素を削除できる 積集合 (intersection) または交差点 (subtraction)
ExceptWith(IEnumerable<T>) 指定のコレクションにある要素を削除できる 減算 (subtraction)
SymmetricExceptWith(IEnumerable<T>) どちらか一方にある要素だけになるように、削除と追加をする 対象差 (symmetric difference)
int[] a1 = { 1, 2, 3, 4 };
int[] a2 = { 3, 4, 5, 6 };

HashSet<int> h1 = new HashSet<int>(a1);
HashSet<int> h2 = new HashSet<int>(a1);
HashSet<int> h3 = new HashSet<int>(a1);
HashSet<int> h4 = new HashSet<int>(a1);

h1.UnionWith(a2);           // 1, 2, 3, 4, 5, 6
h2.IntersectWith(a2);       // 3, 4
h3.ExceptWith(a2);          // 1, 2
h4.SymmetricExceptWith(a2); // 1, 2, 5, 6

TryGetValue(T, T)

public bool TryGetValue (T equalValue, out T actualValue);
HashSet<T>.TryGetValue(T, T) Method (System.Collections.Generic) | Microsoft Learn

equalValueが見つかったならば、その値自体がactualValueに格納されます。TryGetValue - HashSet.cs

Add(T)

public bool Add (T item);
HashSet<T>.Add(T) メソッド (System.Collections.Generic) | Microsoft Learn

要素が追加された場合にはtrue、すでに存在しているために追加されなかった場合にはfalseが返されます。

このメソッドの計算量はO(1)ですが、追加のために容量を増加させる必要があるときにはO(n)となります。このときnは、Countプロパティの値です。

追加するたびにハッシュが求められ、それと一致する要素が存在しないか確認されるため、1回の操作は高価です。Add - HashSet.cs

HashSet<int> hashSet = new HashSet<int>();
bool r1 = hashSet.Add(1);  // true
bool r2 = hashSet.Add(10); // true
bool r3 = hashSet.Add(10); // false
bool r4 = hashSet.Add(5);  // true

foreach (int item in hashSet)
{
    Console.Write(item); // 1,10,5
}

複数の要素の追加

  • オブジェクトの生成時に追加できるならば、コンストラクタで渡す
  • UnionWith()でマージする
  • Array.ForEach()で、Add()をくり返し呼ぶ
int[] a = { 1, 2, 3 };

HashSet<int> h1 = new HashSet<int>(a);

HashSet<int> h2 = new HashSet<int>();
h2.UnionWith(a);

HashSet<int> h3 = new HashSet<int>();
Array.ForEach(a, x => h3.Add(x));

Remove(T)

public bool Remove (T item);
HashSet<T>.Remove(T) メソッド (System.Collections.Generic) | Microsoft Learn

要素が削除された場合にはtrue、要素が見つからないなどして削除されなかった場合にはfalseが返されます。Remove - HashSet.cs

このメソッドの計算量はO(1)です。

RemoveWhere(Predicate<T>)

public int RemoveWhere (Predicate<T> match);
HashSet<T>.RemoveWhere(Predicate<T>) メソッド (System.Collections.Generic) | Microsoft Learn

matchに一致したすべての要素が削除され、その削除された数が返されます。

Contains(T)

このメソッドの計算量はO(1)です。Remarks - HashSet<T>.Contains(T) Method (System.Collections.Generic) | Microsoft Learn

CopyTo(T[])

public void CopyTo (T[] array);
CopyTo(T[]) - HashSet<T>.CopyTo メソッド (System.Collections.Generic) | Microsoft Learn

arrayにコピーされます。

HashSet<int> hashSet = new HashSet<int> { 1, 2, 3 };

int[] array = new int[hashSet.Count];
hashSet.CopyTo(array);

Collectionへの変換

HashSetはIList<T>を実装しないため、Collectionのコンストラクタへは直接渡せません。

HashSet<int> hashSet = new HashSet<int> { 1, 2, 3 };

Collection<int> c1 = new Collection<int>(hashSet);
// error CS1503: 引数 1: は 'System.Collections.Generic.HashSet<int>' から 'System.Collections.Generic.IList<int>' へ変換することはできません。

しかしList<T>はこれを実装するため、そのコンストラクタまたはLinq.ToList()を介して渡すことでCollectionへ変換できます。

List<int> list = new List<int>(hashSet);
Collection<int> c2 = new Collection<int>(list);

Collection<int> c3 = new Collection<int>(hashSet.ToList());

このときListのコンストラクタの呼び出しでは、HashSet<T>のCopyTo()の実装により、すべての要素の参照が順に複製されます。CopyTo - HashSet.cs

Microsoft Learnから検索