【问题标题】:Should I use a C# Dictionary if I only need fast lookup of keys, and values are irrelevant?如果我只需要快速查找键并且值无关紧要,我应该使用 C# 字典吗?
【发布时间】:2017-07-23 21:58:12
【问题描述】:

我需要一种能够插入条目然后能够快速确定是否已插入条目的数据类型。 Dictionary 似乎适合这种需要(参见示例)。但是,我对字典的values 没有用处。我应该仍然使用字典还是有其他更适合的数据类型?

public class Foo
{
    private Dictionary<string, bool> Entities;

    ...

    public void AddEntity(string bar)
    {
        if (!Entities.ContainsKey(bar))
        {
            // bool value true here has no use and is just a placeholder
            Entities.Add(bar, true);
        }
    }

    public string[] GetEntities()
    {
        return Entities.Keys.ToArray();
    }

}

【问题讨论】:

  • 关于这个主题的一个有趣的旁注:Java 的 HashSet 实际上只是 HashMap 的包装。他们完全按照你的建议做,但他们在上面放了一张更漂亮的脸。 =)
  • stackoverflow.com/questions/2728500/…统计比较显示为图表

标签: c# dictionary lookup


【解决方案1】:

您可以使用HashSet&lt;T&gt;

HashSet&lt;T&gt; 类提供高性能的集合操作。一套 是一个不包含 重复元素的集合,并且其 元素没有特定的顺序

【讨论】:

  • 请注意,与字典不同的是,在添加之前无需检查是否存在。
  • @Evk - 如果您使用索引器,也不需要在添加到字典之前检查是否存在。
  • 是的,但如果该信息因其他原因有用,HashSet&lt;T&gt;.Add() 会返回一个 bool 指示该项目是否已成功添加(之前没有)
  • @pinkfloydx33 不知道!刚刚设法从我们的系统中删除了大约 30 行代码,因为我们编写了一个辅助方法来做到这一点!谢谢
  • @MatthewSteeples 在这种情况下,我觉得我应该提到HashSet&lt;T&gt;.Remove 的工作方式相同。它返回一个booltrue 如果找到并删除了该项目,则 false 否则。不抛出异常,无需调用Contains
【解决方案2】:

Habib's answer 非常好,但是对于多线程环境,如果您使用HashSet&lt;T&gt;,那么您必须使用locks 来保护对它的访问。我发现自己更容易使用lock 语句造成死锁。此外,locks 对每个 Amdahl's law 产生的加速效果更差,因为添加 lock 语句会降低实际并行代码的百分比。

出于这些原因,ConcurrentDictionary&lt;T,object&gt; 符合多线程环境的要求。如果您最终使用了一个,那么就像您在问题中所做的那样包装它。只需 new 向上 objects 根据需要将值作为值折腾,因为这些值并不重要。 您可以验证其lock 中没有source code 语句

如果您不需要集合的可变性,那么这将是没有意义的。但您的问题暗示您确实需要它,因为您有一个 AddEntity 方法。

附加信息 2017-05-19 - 实际上,ConcurrentDictionary 确实在内部使用了锁,尽管 lock 声明不是本身 --它使用Monitor.Enter(查看TryAddInternal方法)。但是,它似乎锁定了字典中的各个存储桶,这意味着与将整个内容放在 lock 语句中相比,争用更少。

总而言之,ConcurrentDictionary 通常更适合多线程环境。

仅使用Interlocked 方法来创建并发散列集实际上非常困难(不可能?)。我自己尝试过,但一直遇到需要同时更改两件事的问题——通常只有锁定才能做到这一点。我发现的一种解决方法是对哈希桶使用单链表,并在一个线程需要在一个节点上操作而不受其他线程干扰时有意在列表中创建循环;这将导致其他线程在同一位置旋转,直到该线程完成其节点并取消循环。当然,从技术上讲,它没有使用锁,但扩展性不好。

【讨论】:

    猜你喜欢
    • 2011-09-15
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    相关资源
    最近更新 更多