HashSet<T> t = new HashSet<T>();
// add 10 million items
Dictionary<K, V> t = new Dictionary<K, V>();
// add 10 million items.
谁的.Contains
方法会更快返回?
只是为了澄清,我的要求是我有1000万个对象(好吧,字符串),我需要检查它们是否存在于数据结构中。我永远不会迭代。
答案 0 :(得分:137)
HashSet vs List vs Dictionary性能测试,取自here。
添加1000000个对象(不检查重复项)
包含对10000
集合中一半对象的检查
删除10000个
集合中的一半对象
答案 1 :(得分:69)
我认为你在第二种情况下的意思是Dictionary<TKey, TValue>
? HashTable
是非泛型类。
您应该根据实际需求为作业选择合适的收藏。你实际上想要将每个键映射到一个值吗?如果是,请使用Dictionary<,>
。如果您仅将其视为一组,请使用HashSet<>
。
我希望HashSet<T>.Contains
和Dictionary<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)
该问题的公认答案不能有效回答该问题!碰巧可以给出正确的答案,但是他们提供的证据并未显示该答案。
答案显示的是,在Dictionary
或HashSet
上进行键查找要比在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");
}
}