挿入順序を保持する HashSet が必要です。フレームワークにこれの実装はありますか?
26708 次
4 に答える
40
標準 .NETHashSet
は挿入順序を保持しません。
単純なテストでは、事故によって挿入順序が保持される場合がありますが、保証されているわけではなく、常にそのように機能するとは限りません。間にいくつかの削除を行うだけで十分であることを証明するため。
詳細については、この質問を参照してください: HashSet は挿入順序を保持しますか?
HashSet
挿入順序を保証する を簡単に実装しました。を使用しDictionary
てアイテムを検索し、 を使用しLinkedList
て順序を保持します。3 つの挿入、削除、検索はすべて O(1) でも機能します。
public class OrderedSet<T> : ICollection<T>
{
private readonly IDictionary<T, LinkedListNode<T>> m_Dictionary;
private readonly LinkedList<T> m_LinkedList;
public OrderedSet()
: this(EqualityComparer<T>.Default)
{
}
public OrderedSet(IEqualityComparer<T> comparer)
{
m_Dictionary = new Dictionary<T, LinkedListNode<T>>(comparer);
m_LinkedList = new LinkedList<T>();
}
public int Count => m_Dictionary.Count;
public virtual bool IsReadOnly => m_Dictionary.IsReadOnly;
void ICollection<T>.Add(T item)
{
Add(item);
}
public bool Add(T item)
{
if (m_Dictionary.ContainsKey(item)) return false;
var node = m_LinkedList.AddLast(item);
m_Dictionary.Add(item, node);
return true;
}
public void Clear()
{
m_LinkedList.Clear();
m_Dictionary.Clear();
}
public bool Remove(T item)
{
if (item == null) return false;
var found = m_Dictionary.TryGetValue(item, out var node);
if (!found) return false;
m_Dictionary.Remove(item);
m_LinkedList.Remove(node);
return true;
}
public IEnumerator<T> GetEnumerator()
{
return m_LinkedList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public bool Contains(T item)
{
return item != null && m_Dictionary.ContainsKey(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
m_LinkedList.CopyTo(array, arrayIndex);
}
}
于 2013-07-25T08:41:39.997 に答える