繁体   English   中英

高效的对象平等C#

[英]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可以全部为stringint32DateTime类型。

当它达到数百万次时, .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排序列表中的每个元素

扩大你的团体

如果您不太在乎内存,则可以对结果进行哈希处理以进一步优化组。 基本上构造一个网格... 这是非常具体的,具体取决于您的问题

这背后的想法是隔离真正不相等的事物,这是对先前想法的扩展,但是随着组的增加,组越小,您的性能越快

这样你就可以有十组

  • 少于5个字符的字符串
  • 5至50个字符的字符串
  • 超过50个字符的字符串

等等...

如果您重做数学运算(同样,对于均匀分布的样本)

总迭代次数= 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM