[英]Efficient Object Equality C#
我正在尝试提高以下(示例)代码的性能。
Object[] inputKeys = new Object[10];
inputKeys[0] = "4021";
inputKeys[1] = "3011";
inputKeys[2] = "1010";
inputKeys[3] = "1020";
inputKeys[4] = "1030";
然后比较输入键。
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
bool result = inputKeys[i].Equals(inputKeys[j]);
}
}
inputKeys可以全部为string
, int32
或DateTime
类型。
当它达到数百万次时, .Equals
行的性能将大大下降。
关于如何提高此行的性能(相等性检查)的任何建议吗?
我已经尝试过:使用以下类的数组而不是Object数组来保存键。 我在那里保存密钥类型和密钥值。
public class CustomKey : IEquatable<CustomKey>{
internal int KeyType { get; private set; }
internal string ValueString { get; private set; }
internal int ValueInteger { get; private set; }
internal DateTime ValueDateTime { get; private set; }
internal CustomKey(string keyValue)
{
this.KeyType = 0;
this.ValueString = (string)keyValue;
}
internal CustomKey(int keyValue)
{
this.KeyType = 1;
this.ValueInteger = (int)keyValue;
}
internal CustomKey(DateTime keyValue)
{
this.KeyType = 2;
this.ValueDateTime = (DateTime)keyValue;
}
public bool Equals(CustomKey other)
{
if (this.KeyType != other.KeyType)
{
return false;
}
else
{
if (this.KeyType == 0)
{
return this.ValueString.Equals(other.ValueString);
}
else if (this.KeyType == 1)
{
return this.ValueInteger.Equals(other.ValueInteger);
}
else if (this.KeyType == 2)
{
return this.ValueDateTime.Equals(other.ValueDateTime);
}
else
{
return false;
}
}
}
}
但是性能较差。
您的比较循环效率低下。 我建议您尝试使用:
Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
为该类型定义IEqualityComparer
并将其传递给该方法。 您不会遇到麻烦,但是您将获得一个IEnumerable
其中包含没有重复项的列表。
作为算法效率的示例,您的第一个代码可以被重写
for (int i = 0; i < 5; i++)
{
for (int j = i; j < 5; j++)
{
bool result = inputKeys[i].Equals(inputKeys[j]);
}
}
因为x.Equals(y)的结果与y.Equals的结果相同,所以您无需同时检查两种方法。 http://msdn.microsoft.com/zh-CN/library/ms173147(v=vs.80).aspx
平等的新实施应遵循以下所有保证
x.Equals(y)返回与y.Equals(x)相同的值。
如评论中所述,算法的主要负担是必须将所有内容与所有内容进行比较,这会降低性能。 对于100K元素,这意味着100k ^ 2 ...或大约10K百万组合...您可以看到问题所在。 最好的选择是修改算法, 但是 ,如果您仍然确定或没有其他选择,请考虑:
首先划分对象,然后再比较:
示例:如果您有100K个对象均匀分布,则将有33K个整数,33K个字符串和33K个日期时间,然后可以相互比较,而忽略它们之间的组合。
100K ^ 2 = 1亿
(30K ^ 2)* 3 = 27亿组合+ 100K排序列表中的每个元素
扩大你的团体
如果您不太在乎内存,则可以对结果进行哈希处理以进一步优化组。 基本上构造一个网格... 这是非常具体的,具体取决于您的问题 。
这背后的想法是隔离真正不相等的事物,这是对先前想法的扩展,但是随着组的增加,组越小,您的性能越快
这样你就可以有十组
等等...
如果您重做数学运算(同样,对于均匀分布的样本)
总迭代次数= 10K ^ 2 * 10 + 100K〜1亿次迭代(10组+组成这些组的价格)
实际复杂度=(n / m)^ 2 * m + n(其中n =元素数量,m =假设分布均匀的组数)。
尝试获取每个对象的哈希码,并将它们与object.GetHashCode()
进行比较。 不确定调用GetHashCode()
数百万次的开销,但是比较两个int可能比Equals(object)
方法要快得多。
使用哈希表(或更好的字典)来存储您的项目。 您的方法的阶数为(N ^ 2),通过使用哈希表,您可以将运行时间复杂度降低为O(N),其中N是数字。
为此,请使用哈希键创建一个哈希表,如果发生冲突,请向链接列表中添加项目。 当只需要检查相同存储桶中的对象是否相等时,就不应该太多。
我希望这是清楚而有用的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.