Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 保留顺序的哈希集_C#_.net_Hashset - Fatal编程技术网

C# 保留顺序的哈希集

C# 保留顺序的哈希集,c#,.net,hashset,C#,.net,Hashset,我需要一个保留插入顺序的哈希集,框架中是否有这种实现?标准.NET哈希集不保留插入顺序。 对于简单的测试,插入顺序可能会因为意外而保留,但不能保证,也不能总是这样。证明在两者之间进行一些删除就足够了 有关这方面的更多信息,请参见此问题: 我已经简单地实现了一个HashSet,它保证了插入顺序。它使用字典查找项目,并使用链接列表保持顺序。所有三个插入、删除和查找操作仍在O(1)中进行 公共类OrderedSet:ICollection { 专用只读词典; 私有只读链接列表Mu链接列表; 公共Ord

我需要一个保留插入顺序的哈希集,框架中是否有这种实现?

标准.NET
哈希集
不保留插入顺序。
对于简单的测试,插入顺序可能会因为意外而保留,但不能保证,也不能总是这样。证明在两者之间进行一些删除就足够了

有关这方面的更多信息,请参见此问题:

我已经简单地实现了一个
HashSet
,它保证了插入顺序。它使用
字典
查找项目,并使用
链接列表
保持顺序。所有三个插入、删除和查找操作仍在O(1)中进行

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

通过为TKey和TItem指定相同的类型参数,可以轻松获得此功能:

public class OrderedHashSet<T> : KeyedCollection<T, T>
{
    protected override T GetKeyForItem(T item)
    {
        return item;
    }
}
公共类OrderedHashSet:KeyedCollection { 受保护的覆盖T GetKeyForItem(T项) { 退货项目; } }
如果您需要不断增加
添加
删除
包含
和订单保留的复杂性,那么.NET Framework 4.5中就没有这样的集合

如果您对第三方代码满意,请查看我的存储库(MIT许可证):

OrderedHashSet
集合:

  • 基于经典
    HashSet
    源代码(来自.NET核心)
  • 保留插入顺序并允许手动重新排序
  • 功能反向枚举
  • 具有与哈希集相同的操作复杂性
  • Add
    Remove
    操作比
    HashSet
    慢20%
  • 每项多消耗8字节内存

我想你是说,就像Java一样,最简单的方法就是将链表和哈希集包装在一起。。。这就是我过去所做的。对于LRU实现很有用。根据集合的定义,集合不应保留任何顺序。@vash代替该注释,问题应该是“我需要一个保留插入顺序并具有哈希集访问特性的数据结构,即O(1)等。”您应该提供一个重载,将
IEqualityComparer
传递给
IDictionary
的相同重载。您的示例开箱即用,通过对象引用(至少对于类)检查相等性,并且不提供更改该行为的选项。然而,我明白这是一个简单的例子。@SimonBelanger同意。我刚刚发布了一个版本,在这里实现了常见构造函数和方法的所有变体:is't
m_LinkedList.Remove(node)实际上是O(n)?@HimBromBeere-好问题。是的,但实际上不是。如果你想删除一个特定的元素,因为你必须找到这个元素,那么删除本身就是O(1)。如果你看一下我的实现,我们使用字典来查找它,它是O(1),而不是列表。首先,当你调用
Remove
时,它会调用还是?第一个是O(n),第二个是O(1)。它调用
Remove(TKey)
,因为它是最派生类上的一个。但是,当集合强制转换为集合或ICollection时调用Remove()将调用
Remove(T)
重载。另一个说明是:
Remove(T)
Remove(TKey)
都是O(n)因为
KeyedCollection
使用列表存储项目。请注意,与常规的
System.Collections.Generic.HashSet
不同,这将在重复键上抛出
System.ArgumentException
,而不是返回
false
@kcnygaard-为什么您认为KeyedCollection保持插入顺序?在内部,它只是一本字典,它是。
public class OrderedHashSet<T> : KeyedCollection<T, T>
{
    protected override T GetKeyForItem(T item)
    {
        return item;
    }
}