Office中国论坛/Access中国论坛
标题: 【原创】GetHashCode与Comparer相互调用关系 [打印本页]
作者: faunus 时间: 2014-2-24 11:17
标题: 【原创】GetHashCode与Comparer相互调用关系
本帖最后由 faunus 于 2014-2-24 11:18 编辑
不多说了,先上代码:
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- public class Comparer : IEqualityComparer<int>
- {
- public int countEquals = 0;
- public int countGetHashCode = 0;
- public bool Equals(int x, int y)
- {
- countEquals++;
- Console.WriteLine(" ->Equals:{0:00},{1:00}", x, y);
- return x == y;
- }
- public int GetHashCode(int x)
- {
- countGetHashCode++;
- Console.WriteLine("X:{0:00},GetHashCode:{1:00}", x, x % 7);
- return x % 7;
- return countGetHashCode;
- return 0x7FFFFFFF;
- }
- }
- class TestA
- {
- static void Main(string[] args)
- {
- List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 7, 14, 21, 28, 35 };
- //List<int> list = new List<int> { 1, 4, 5, 2, 4, 10, 3, 4, 15 };//用于证明调用顺序
- Comparer comparer = new Comparer();
- int count = list.Distinct(comparer).Count();
- Console.WriteLine("共" + count + "条不重复数据");
- Console.WriteLine("GetHashCode:调用{0}次,Equals:调用:{1}次!", comparer.countGetHashCode, comparer.countEquals);
- Console.ReadKey();
- }
- }
复制代码
作者: faunus 时间: 2014-2-24 11:17
[size=14.399999618530273px]结果如下:
X:01,GetHashCode:01
X:02,GetHashCode:02
X:03,GetHashCode:03
X:04,GetHashCode:04
X:05,GetHashCode:05
X:06,GetHashCode:06
X:06,GetHashCode:06
->Equals:06,06
X:06,GetHashCode:06
->Equals:06,06
X:06,GetHashCode:06
->Equals:06,06
X:06,GetHashCode:06
->Equals:06,06
X:07,GetHashCode:00
X:14,GetHashCode:00
->Equals:07,14
X:21,GetHashCode:00
->Equals:14,21
->Equals:07,21
X:28,GetHashCode:00
->Equals:21,28
->Equals:14,28
->Equals:07,28
X:35,GetHashCode:00
->Equals:28,35
->Equals:21,35
->Equals:14,35
->Equals:07,35
共11条不重复数据
GetHashCode:调用15次,Equals:调用:14次!
[size=14.399999618530273px]总结:
[1]分为三种情况
A:Hash码不同,值不同.
GetHashCode执行1次,Equals未调用.
B:Hash码相同,值相同.
GetHashCode执行1次,Equals调用0次(首个)或1次(余下).
C:Hash码相同,值不同.
GetHashCode执行1次,Equals调用0次(首个)1次(第2)....n-1次(第n)
C:Hash码不同,值相同.
不允许存在这种情况
[2]GetHashCode的执行效率
完全散列:O (1)
完全不散列:O (n*n)
[3]GetHashCode自动调用Equals
这又是一个编译器魔法,
GetHashCode是在冲突的情况下才去调用Equals
如果GetHashCode设计的足够好,可以极大提高查询效率.
[4]GetHashCode的正确性保障
-----------正确情况--------------
GetHashCode相同,Equals必相同(重码)
GetHashCode不同,Equals可相同(不充分散列,效率低)
GetHashCode不同,Equals不相同(充分散列)
-----------错误情况--------------
GetHashCode相同,Equals不相同(导致不可预料的错误)
作者: faunus 时间: 2014-2-24 11:17
[size=14.399999618530273px]其它一些方法的影响:
[size=14.399999618530273px]
[size=14.399999618530273px]- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- public class Comparer : IEqualityComparer<int>
- {
- public int countEquals = 0;
- public int countGetHashCode = 0;
- public bool Equals(int x, int y)
- {
- countEquals++;
- Console.Write("->Equals:{0:00},{1:00}", x, y);
- return x == y;
- }
- public int GetHashCode(int x)
- {
- countGetHashCode++;
- Console.WriteLine();
- Console.Write("X:{0:00},GetHashCode:{1:00}", x, x % 7);
- return x % 7;
- }
- }
- class TestA
- {
- static void Main(string[] args)
- {
- Comparer comparer = new Comparer();
- Dictionary<int, int> dic = new Dictionary<int, int>(comparer)
- {
- { 1, 1 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 1 },
- //{ 6, 1 }, { 6, 1 }, { 6, 1 }, { 6, 1 }, { 6, 1 },
- { 7, 1 }, { 14, 1 }, { 21, 1 }, { 28, 1 }, { 35, 1 }
- };
- Console.WriteLine();
- Console.WriteLine();
- Console.Write("dic.Add(99, 1);");
- dic.Add(99, 1);
- Console.WriteLine();
- Console.Write("dic.ContainsKey(99);");
- dic.ContainsKey(99);
- Console.WriteLine();
- Console.Write("dic.ContainsKey(98);");
- dic.ContainsKey(98);
- Console.WriteLine();
- Console.Write("dic.ContainsValue(1);");
- dic.ContainsValue(1);
- Console.WriteLine();
- Console.Write("dic.Remove(35);");
- dic.Remove(35);
- int val;
- Console.WriteLine();
- Console.Write("dic.TryGetValue(97, out val);");
- dic.TryGetValue(97, out val);
- Console.WriteLine();
- Console.Write("dic.TryGetValue(97, out val);");
- dic.TryGetValue(99, out val);
- Console.WriteLine();
- Console.WriteLine();
- int count = dic.Distinct().Count();
- Console.WriteLine("共" + count + "条不重复数据");
- Console.WriteLine("GetHashCode:调用{0}次,Equals:调用:{1}次!", comparer.countGetHashCode, comparer.countEquals);
- Console.ReadKey();
- }
- }
复制代码
作者: faunus 时间: 2014-2-24 11:18
结果如下:
X:01,GetHashCode:01
X:02,GetHashCode:02
X:03,GetHashCode:03
X:04,GetHashCode:04
X:05,GetHashCode:05
X:07,GetHashCode:00
X:14,GetHashCode:00->Equals:07,14
X:21,GetHashCode:00->Equals:14,21->Equals:07,21
X:28,GetHashCode:00->Equals:21,28->Equals:14,28->Equals:07,28
X:35,GetHashCode:00->Equals:28,35->Equals:21,35->Equals:14,35->Equals:07,35
dic.Add(99, 1);
X:99,GetHashCode:01->Equals:01,99
dic.ContainsKey(99);
X:99,GetHashCode:01->Equals:99,99
dic.ContainsKey(98);
X:98,GetHashCode:00->Equals:35,98->Equals:28,98->Equals:21,98->Equals:14,98->Equals:07,98
dic.ContainsValue(1);
dic.Remove(35);
X:35,GetHashCode:00->Equals:35,35
dic.TryGetValue(97, out val);
X:97,GetHashCode:06
dic.TryGetValue(97, out val);
X:99,GetHashCode:01->Equals:99,99
共10条不重复数据
GetHashCode:调用16次,Equals:调用:19次!
欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) |
Powered by Discuz! X3.3 |