O(A*B)优化到O(A+B)

先看看代码,很多时候都用到Contains,2个对象相同的取出相同的对象。
代码片段如下:

public class Order2
{
    private int _OrderId { get; set; }
    private string _ProductName{get;set;}

    public Order2(int x, string p)
    {
        _OrderId = x;
        _ProductName = p;
    }

    public int OrderId
    {
        get { return _OrderId; }
        set { _OrderId = value; }
    }


    public string ProductName
    {
        get{return _ProductName;}
        set{_ProductName=value;}
    }
}



这里的意思是跟据相同的OrderID就可以匹配了,ProductName无需匹配

/// <summary>
/// EqualityComparer 规则,详细请看msdn
/// 用途:并集,交集,差集 Linq 的 IEnumerable 制定特定的规则
/// </summary>
public class ComparerRule : IEqualityComparer<Order2>
{
    public static ComparerRule Defaut = new ComparerRule();

    public bool Equals(Order2 x, Order2 y)
    {
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        return x.OrderId == y.OrderId;
    }

    public int GetHashCode(Order2 obj)
    {

        if (Object.ReferenceEquals(obj, null)) return 0;

        int orderhashcode = obj.OrderId.GetHashCode();

        return orderhashcode;
    }
}

 

static void Main(string[] args)
        {
            for (int k = 0; k < 10; k++)
            {
                List<Order2> A = new List<Order2>();
                List<Order2> B = new List<Order2>();

                HashSet<Order2> C = new HashSet<Order2>();

                for (int i = 0; i < 10000; i++)
                {
                    A.Add(new Order2(rand.Next(10000), "产品" + i.ToString()));
                    int temp = rand.Next(10000);
                    B.Add(new Order2(temp, ""));
                    C.Add(new Order2(temp, ""));
                }

                ////这里复杂度是A*B
                long T1 = DateTime.Now.Ticks;
                List<Order2> result1 = new List<Order2>();
                foreach (Order2 p in A)
                {
                    if (B.Contains<Order2>(p, ComparerRule.Defaut))
                    {
                        result1.Add(p);
                    }
                }
                Console.WriteLine(result1.Count());
                Console.WriteLine("List执行时间:" + TimeSpan.FromTicks(DateTime.Now.Ticks - T1).Milliseconds + "毫秒");

                ////这里复杂度是A+B
                long T2 = DateTime.Now.Ticks;
                List<Order2> result2 = new List<Order2>();
                foreach (Order2 p in A)
                {
                    if (C.Contains<Order2>(p, ComparerRule.Defaut))
                    {
                        result2.Add(p);
                    }
                }
                Console.WriteLine(result2.Count());
                Console.WriteLine("HashSet执行时间:" + TimeSpan.FromTicks(DateTime.Now.Ticks - T2).Milliseconds + "毫秒");
            
            }
            Console.Read();
        }


看下执行结果,并没有感觉hashset提升了多少效果。估计跟IEqualityComparer接口有关系。
$KR}R}][@P`VS_VT1D@A`F8



代码进一步修改。

public class ABContains
    {
        public static List<Order2> Contains(List<Order2> I1, List<Order2> I2)
        {
            var list = Array.ConvertAll<Order2, long>(I2.ToArray(), delegate(Order2 output)
            {
                return output.OrderId;
            });


            HashSet<long> Target = new HashSet<long>(list);


            List<Order2> Result = new List<Order2>();

            foreach (Order2 p in I1)
            {
                if (Target.Contains(p.OrderId))
                {
                    Result.Add(p);
                }
            }

            return Result;
        }
    }
            long T3 = DateTime.Now.Ticks;
            List<Order2> o = ABContains.Contains(A, B);
            Console.WriteLine(o.Count());
            Console.WriteLine("ABContains执行时间:" + TimeSpan.FromTicks(DateTime.Now.Ticks - T3).Milliseconds + "毫秒");
……


执行结果,其中有一部分是转换花的时间,效果显而易见。

I5U)7CG81U{)`_85~L{K2G5

posted @ 2016-01-11 13:06  kfsmqoo  阅读(230)  评论(0编辑  收藏  举报