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接口有关系。
代码进一步修改。
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 + "毫秒");
……
执行结果,其中有一部分是转换花的时间,效果显而易见。