C# 无重复但有顺序的集合,具有快速包含检查和添加/删除

C# 无重复但有顺序的集合,具有快速包含检查和添加/删除,c#,collections,C#,Collections,我正在寻找一个集合,它具有快速的包含检查和添加/删除方法(如HashSet,如果T实现得很好,则接近O(1)),但它也有一个顺序。这并不意味着索引访问——它只意味着如果我对它进行迭代,元素的顺序与我添加它们的顺序相同 C#中有类似的东西吗?HashSet真的做到了吗?(我在MSDN上找不到这个信息,我检查了HashSet和HashSet.GetEnumerator) 如果没有,我想用一个包含内部哈希集和内部链接列表的类来实现它。HashSet将公开添加、删除和包含检查,而LinkedList将公

我正在寻找一个集合,它具有快速的包含检查和添加/删除方法(如
HashSet
,如果
T
实现得很好,则接近O(1)),但它也有一个顺序。这并不意味着索引访问——它只意味着如果我对它进行迭代,元素的顺序与我添加它们的顺序相同

C#中有类似的东西吗?
HashSet
真的做到了吗?
(我在MSDN上找不到这个信息,我检查了
HashSet
HashSet.GetEnumerator


如果没有,我想用一个包含内部
哈希集
和内部
链接列表
的类来实现它。
HashSet
将公开添加、删除和包含检查,而
LinkedList
将公开枚举数。

您似乎正在寻找

唯一的缺点是它不支持泛型,但是您可以很容易地在它周围做一个包装,或者只是将值强制转换为您需要的类型

编辑:如注释中所述,您可以在中找到一个“OrderedSet”的实现,该实现满足您的确切需求(并使用
链接列表和
哈希集
实现),这可能对您有用

这是它们的实现(学分归原作者,而不是我

公共类OrderedSet:ICollection
{
专用只读词典;
私有只读链接列表Mu链接列表;
公共OrderedSet()
:此(EqualityComparer.Default)
{
}
公共OrderedSet(IEqualityComparer比较程序)
{
m_Dictionary=新字典(比较器);
m_LinkedList=新建LinkedList();
}
公共整数计数
{
获取{return m_Dictionary.Count;}
}
公共虚拟bool是只读的
{
获取{return m_Dictionary.IsReadOnly;}
}
作废ICollection.Add(T项)
{
增加(项目);
}
公共布尔添加(T项)
{
if(m_Dictionary.ContainsKey(item))返回false;
LinkedListNode节点=m_LinkedList.AddLast(项);
m_Dictionary.Add(项,节点);
返回true;
}
公共空间清除()
{
m_LinkedList.Clear();
m_Dictionary.Clear();
}
公共布尔删除(T项)
{
LinkedListNode节点;
bool found=m_Dictionary.TryGetValue(项,out节点);
如果(!found)返回false;
m_字典。删除(项);
m_LinkedList.Remove(节点);
返回true;
}
公共IEnumerator GetEnumerator()
{
返回m_LinkedList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
返回GetEnumerator();
}
公共布尔包含(T项)
{
返回m_Dictionary.ContainsKey(项目);
}
public void CopyTo(T[]数组,int arrayIndex)
{
m_LinkedList.CopyTo(数组、数组索引);
}
}

HashTable
do?您提议的实现将有O(n)项删除,而不是O(1)。是一个选项。也是相关的:将有O(n)添加和删除。@Servy您有任何证据证明您的声明吗?只有在按键删除时,您才正确。对于其他操作,它是O(1)。对于添加项,它需要在数组列表中搜索密钥对的索引,这是一个O(n)操作。您可以查看源代码以自行查看。你有证据证明你的索赔是O(1)吗?对我来说,Add看起来像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
    {
        get { return m_Dictionary.Count; }
    }

    public virtual bool IsReadOnly
    {
        get { return m_Dictionary.IsReadOnly; }
    }

    void ICollection<T>.Add(T item)
    {
        Add(item);
    }

    public bool Add(T item)
    {
        if (m_Dictionary.ContainsKey(item)) return false;
        LinkedListNode<T> 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)
    {
        LinkedListNode<T> node;
        bool found = m_Dictionary.TryGetValue(item, out 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 m_Dictionary.ContainsKey(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        m_LinkedList.CopyTo(array, arrayIndex);
    }
}