HashSet <t>与Dictionary <k,v =“”> w.r.t搜索时间以查找项目是否存在</k,> </t>

时间:2010-04-28 10:11:19

标签: .net performance dictionary hashset

HashSet<T> t = new HashSet<T>();
// add 10 million items


Dictionary<K, V> t = new Dictionary<K, V>();
// add 10 million items.

谁的.Contains方法会更快返回?

只是为了澄清,我的要求是我有1000万个对象(好吧,字符串),我需要检查它们是否存在于数据结构中。我永远不会迭代。

5 个答案:

答案 0 :(得分:137)

HashSet vs List vs Dictionary性能测试,取自here

添加1000000个对象(不检查重复项)

包含对10000

集合中一半对象的检查

删除10000个

集合中的一半对象

答案 1 :(得分:69)

我认为你在第二种情况下的意思是Dictionary<TKey, TValue>HashTable是非泛型类。

您应该根据实际需求为作业选择合适的收藏。你实际上想要将每个键映射到一个值吗?如果是,请使用Dictionary<,>。如果您将其视为一组,请使用HashSet<>

我希望HashSet<T>.ContainsDictionary<TKey, TValue>.ContainsKey(这是可比较的操作,假设您明智地使用词典)基本上执行相同的操作 - 从根本上说它们使用相同的算法。我想,Dictionary<,>中的条目越大,您最终可能会使用Dictionary<,>而不是使用HashSet<>来释放缓存,但我认为与选择错误数据类型的痛苦仅仅取决于你想要实现的目标。

答案 2 :(得分:4)

这些是不同的数据结构。此外,还没有HashTable的通用版本。

HashSet包含类型为T的值HashTable(或Dictionary)包含键值对。因此,您应该选择需要存储哪些数据的集合。

答案 3 :(得分:4)

来自词典&lt; TKey,TValue&gt;

的MSDN文档
  

&#34;使用其密钥检索值非常快,接近 O(1),因为Dictionary类实现为作为哈希表。 &#34;

附注:

  

&#34;检索速度取决于为TKey指定的类型的哈希算法的质量&#34;

我知道您的问题/帖子已经过时了 - 但在寻找类似问题的答案时,我偶然发现了这一点。

希望这会有所帮助。向下滚动到备注部分以获取更多详细信息。 https://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx

答案 4 :(得分:1)

该问题的公认答案不能有效回答该问题!碰巧可以给出正确的答案,但是他们提供的证据并未显示该答案。

答案显示的是,在DictionaryHashSet上进行键查找要比在List中查找键快得多。这是真的,但并不有趣,也不令人惊讶,也不能证明它们具有相同的速度。

我已经运行了下面的代码来比较查找时间,我的结论是它们实际上是相同的速度。 (或者至少,如果存在任何差异,则该差异完全在该速度的标准偏差之内)

对于我来说,在本次测试中,两亿次查找都耗时10到11.5秒。

测试代码:

private const int TestReps = 100_000_000;
[Test]
public void CompareHashSetContainsVersusDictionaryContainsKey()
{
    for (int j = 0; j < 10; j++)
    {
        var rand = new Random();
        var dict = new Dictionary<int, int>();
        var hash = new HashSet<int>();

        for (int i = 0; i < TestReps; i++)
        {
            var key = rand.Next();
            var value = rand.Next();
            hash.Add(key);
            dict.TryAdd(key, value);
        }

        var testPoints = Enumerable.Repeat(1, TestReps).Select(_ => rand.Next()).ToArray();
        var timer = new Stopwatch();
        var total = 0;
        
        timer.Restart();
            for (int i = 0; i < TestReps; i++)
            {
                var newKey = testPoints[i];
                if (hash.Contains(newKey))
                {
                    total++;
                }
            }
        Console.WriteLine(timer.Elapsed);
        
        var target = total;
        Assert.That(total == target);
        

        timer.Restart();
            for (int i = 0; i < TestReps; i++)
            {
                var newKey = testPoints[i];
                if (dict.ContainsKey(newKey))
                {
                    total++;
                }
            }
        Console.WriteLine(timer.Elapsed);

        Assert.That(total == target * 2);
        Console.WriteLine("Set");
    }
}