【发布时间】:2015-06-03 14:49:36
【问题描述】:
我有一个自定义类,我试图将其用作字典的键:
// I tried setting more than enough capacity also...
var dict = new Dictionary<MyPoint, MyPoint>(capacity);
现在让我明确一点,这里的目标是比较两个相似但不同的列表,使用 X、Y 和 Date 作为复合键。这两个列表的值会有所不同,我正在尝试快速比较它们并计算它们的差异。
这是课程代码:
public class MyPoint : IEquatable<MyPoint>
{
public short X { get; set; }
public short Y { get; set; }
public DateTime Date { get; set; }
public double MyValue { get; set; }
public override bool Equals(object obj)
{
return base.Equals(obj as MyPoint);
}
public bool Equals(MyPoint other)
{
if (other == null)
{
return false;
}
return (Date == other.Date)
&& (X == other.X)
&& (Y == other.Y);
}
public override int GetHashCode()
{
return Date.GetHashCode()
| X.GetHashCode()
| Y.GetHashCode();
}
}
我还尝试使用结构进行键控:
public struct MyPointKey
{
public short X;
public short Y;
public DateTime Date;
// The value is not on these, because the struct is only used as key
}
在这两种情况下,字典的书写速度都非常非常慢(阅读速度很快)。
我把key改成了字符串,格式为:
var dict = new Dictionary<string, MyPoint>(capacity);
var key = string.Format("{0}_{1}", item.X, item.Y);
我对它的速度之快感到惊讶——它至少快了 10 倍。我尝试了发布模式,没有调试器,以及我能想到的所有场景。
这本词典将包含 350,000 或更多项,因此性能很重要。
有什么想法或建议吗?谢谢!
另一个编辑...
我正在尝试以最快的方式比较两个列表。这就是我正在使用的。字典对于快速查找源列表很重要。
IList<MyThing> sourceList;
IDictionary<MyThing, MyThing> comparisonDict;
Parallel.ForEach(sourceList,
sourceItem =>
{
double compareValue = 0;
MyThing compareMatch = null;
if (comparisonDict.TryGetValue(sourceItem, out compareMatch))
{
compareValue = compareMatch.MyValue;
}
// Do a delta check on the item
double difference = sourceItem.MyValue- compareValue;
if (Math.Abs(difference) > 1)
{
// Record the difference...
}
});
【问题讨论】:
-
您已经回答了自己的问题 - 使用复杂类型作为字典的键比使用原始类型慢。
-
记住——不要使用可变对象作为字典键。同样使用不可变点,您可以在点初始化期间计算和存储哈希码。因此,您将拥有原始类型的速度
-
另外,
GetHashCode()使用 |这可能不是最好的方法。 -
@BinkanSalaryman 通常你使用
^(XOR) 来组合哈希码。 -
@BinkanSalaryman 我知道它是什么。我只是说这不是你实现哈希码的方式。一种流行的方法是将每个单独的哈希码乘以一个素数并将它们相加。
标签: c# string dictionary equals gethashcode