高效的对象平等C#

时间:2012-12-18 17:47:44

标签: 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可以是stringint32DateTime类型的所有内容。

.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;
            }
        }
    }
}

但表现更差。

5 个答案:

答案 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组

  • 短于5个字符的字符串
  • 5到50个字符之间的字符串
  • 超过50个字符的字符串

依旧......

如果您重做数学(再次,对于均匀分布的样本)

总迭代次数= 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是数字。

要完成此操作,请使用哈希键创建哈希表,如果您遇到冲突,请将项添加到链接列表。当只需要检查相同桶中的对象是否相等时,不应该太多。

我希望这很清楚,也很有帮助。