字典与唯一性和性能列表

时间:2015-02-24 12:47:37

标签: c# performance dictionary hashset

以下是一个理论问题,但我想知道是否有经验法则回答

让我们设想一个已实施GetHashCode()Equals()方法的课程。

因此,它可以用作Dictionary<T>键或HashSet<T>

现在我想检查N个项目的列表与另一个唯一M项目列表,如果所有Ns彼此唯一且对任何M都是唯一的。

由于它们是字典就绪的,我可以简单地将所有Ms添加到字典中,然后迭代Ns并检查/添加它们,直到我做或不做错。

或者我可以将Ms放入List<T>然后遍历Ns,检查是否相等并将它们添加到M列表中。

我从绩效的角度来看待这个问题。根据哈希码的精选程度,ContainsKey()Add()将导致2(GetHashCode()GetHashCode())或4个函数调用({{1} },GetHashCode()Equals()GetHashCode())。

另一方面,For循环只使用1个函数调用(如果你使用Equals()界面,你可以使用IEquatable<T>),Contains()调用。

但从写作的角度来看,Equals()Dictionary<T>似乎更直观,因为代码会立即告诉您作者的目标(寻找唯一性)。

是否有一些M和N可以选择一个而不是另一个?

额外问题:如果您的标准用例并不期望密钥已经存在,那么只需尝试将密钥添加到HashSet<T>并抓住{{1}而不是使用Dictionary<T>

1 个答案:

答案 0 :(得分:1)

假设您正在谈论算法的渐近复杂性,这意味着N和M非常大。在这种情况下,调用函数如Equals()和GetHashCode()的开销(假设它们当然是O(1))。

如果你想比较一个算法与其他算法的渐近复杂度,那么HashSet会在一般情况下给你最好的结果,因为它在像Contains这样的函数上有O(1)复杂度。

但是,首先需要将元素添加到哈希集中。这可能导致数组创建新数组和复制引用(如果我们在讨论引用类型或值,如果我们讨论值类型)。

同样适用于List和Dictionary,当元素数小于某个内部容量时,它们在添加新项目时也会有O(1)复杂度,否则会增加O(n)。

所以,如果你有一个很好的哈希函数并且你不能对它们之间的输入值进行比较做出假设,这可以降低手工比较它们的复杂性,你可能应该使用HashSet。