我正在尝试提高以下(示例)代码的性能。
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数组来保存键。我保留了Key类型和键值。
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;
}
}
}
}
但表现更差。
答案 0 :(得分:2)
您的比较循环效率低下。我建议你尝试使用:
Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
为该类型定义IEqualityComparer
并将其传递给该方法。你不会得到一个bool,但是你会得到一个IEnumerable
包含没有重复的列表。
答案 1 :(得分:2)
作为算法效率的一个例子,您的第一个代码可以被重写
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/en-us/library/ms173147(v=vs.80).aspx
Equals的新实施应遵循
的所有保证x.Equals(y)返回与y.Equals(x)相同的值。
答案 2 :(得分:1)
正如评论中所说,算法的主要负担是你必须将所有内容与所有内容进行比较,这会让你的表现惨淡。对于100K元素,这意味着100k ^ 2 ......或大约10万个组合......你可以看到你遇到问题的地方。最好的选择是修改算法,然而,如果您仍然确定或者您没有任何其他选择,请考虑:
首先划分对象,稍后进行比较:
示例:如果你有100K个对象,你将有33K整数,33K字符串和33K日期时间,然后你可以相互比较它们并忽略它们之间的组合。
100K ^ 2 = 10万百万
(30K ^ 2)* 3 = 2700万组合+ 100K来订购其列表中的每个元素
扩展您的论坛
如果您对内存不太在意,可以对结果进行哈希处理以进一步优化您的组。基本上构建一个网格... 这取决于您的问题非常具体。
这背后的想法是隔离不能真正平等的东西,它是前一个想法的延伸,但是有更多的群体,群体越小,你的表现越快
这样你可以有10组
依旧......
如果您重做数学(再次,对于均匀分布的样本)
总迭代次数= 10K ^ 2 * 10 + 100K~1亿次迭代(10组+组成这些组的价格)
实际复杂度=(n / m)^ 2 * m + n(其中n =元素数,m =假设均匀分布的组数。
答案 3 :(得分:0)
尝试抓取每个对象的哈希码并将其与object.GetHashCode()
进行比较。不确定调用GetHashCode()
几百万次的开销,但比较两个整数可能会比Equals(object)
方法快得多。
答案 4 :(得分:0)
使用散列表(或更好的词典)来存储您的项目。 你的方法有(N ^ 2)的顺序,通过使用哈希表,你可以将运行时复杂度减少到O(N),其中N是数字。
要完成此操作,请使用哈希键创建哈希表,如果您遇到冲突,请将项添加到链接列表。当只需要检查相同桶中的对象是否相等时,不应该太多。
我希望这很清楚,也很有帮助。