今天说一下C# 中重写public override int GetHashCode()与 public override bool Equals(object obj)
假设我们有Person 类, 向给基于Hash的Collection(比如HashTable和Dictionary)的Key定义Hash值, 有个两个Person 实例 id 不同 ,但是名字相同
代码如下:
在执行 dic.Add(p1, "111"); 时候只会调用GetHashCode。
在执行 dic.Add(p2, "222"); 时候只会调用GetHashCode 不会调用Equals方法,
如果把Person p2的Id 改成和 P1的Id 改成一样则会报ArgumentException {"An item with the same key has already been added."}
这样就可以防止有相同Id 的Person 实例被添加到集合中
所以这样可以证明两个实体相等,他们的HashCode一定相等,但是HashCode相等,两个实体不一定相等
在执行if (dic.ContainsKey(p1))时,会先调用p1的GetHashCode方法,再调Equals方法。
如果我们修改程序,让Id 可以相同,但名字不同的人也可以加入集合dic
在执行 dic.Add(p2, "222"); 时候除了会调用GetHashCode外,还会调用Equals方法
在执行if (dic.ContainsKey(p1))时,会先调用p1的GetHashCode方法,再调Equals方法。 这次会调用两次Equals方法,因为这个时候p1 和 p2在 dic集合里面的HashCode都是一样的。 第一次会让传入的obj和p2进行比较,然后会和p1 和 obj进行比较,最终输出Contains
Java 中这块的原理和C#相同
假设我们有Person 类, 向给基于Hash的Collection(比如HashTable和Dictionary)的Key定义Hash值, 有个两个Person 实例 id 不同 ,但是名字相同
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestGetHashCode
{
class Program
{
static void Main(string[] args)
{
IDictionary<Person, Object> dic = new Dictionary<Person,Object>();
Person p1 = new Person();
p1.Id = 1;
p1.Name = "name1";
p1.Age = 20;
dic.Add(p1, "111");
Person p2 = new Person();
p2.Id = 2;
p2.Name = "name2";
p2.Age = 20;
dic.Add(p2, "222");
if (dic.ContainsKey(p1))
{
Console.WriteLine("Contains");
}
else
{
Console.WriteLine("Not Contains");
}
// IList<Person> list = new List<Person>();
}
}
class Person
{
private object parent;
public object Parent
{
get { return parent; }
set { parent = value; }
}
private int id;
public int Id
{
get { return id; }
set { id = value; }
}
private string name;
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public override int GetHashCode()
{
Console.WriteLine("In GetHashCode");
// Random num = new Random();
// int a = num.Next(1,100);
int hashCode = (this.Id == 0 || this.Id == null) ? 0 : this.Id.GetHashCode();
if (this.parent != null)
{
hashCode = 31 * hashCode + this.parent.GetHashCode();
}
return hashCode;
}
public override bool Equals(object obj)
{
Console.WriteLine("Equal 被执行");
if (obj == null || GetType() != obj.GetType())
{
return false;
}
return this.Id == (obj as Person).Id;
}
}
}
在执行 dic.Add(p1, "111"); 时候只会调用GetHashCode。
在执行 dic.Add(p2, "222"); 时候只会调用GetHashCode 不会调用Equals方法,
如果把Person p2的Id 改成和 P1的Id 改成一样则会报ArgumentException {"An item with the same key has already been added."}
这样就可以防止有相同Id 的Person 实例被添加到集合中
所以这样可以证明两个实体相等,他们的HashCode一定相等,但是HashCode相等,两个实体不一定相等
在执行if (dic.ContainsKey(p1))时,会先调用p1的GetHashCode方法,再调Equals方法。
如果我们修改程序,让Id 可以相同,但名字不同的人也可以加入集合dic
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestGetHashCode
{
class Program
{
static void Main(string[] args)
{
IDictionary<Person, Object> dic = new Dictionary<Person,Object>();
Person p1 = new Person();
p1.Id = 1;
p1.Name = "name1";
p1.Age = 20;
dic.Add(p1, "111");
Person p2 = new Person();
p2.Id = 1;
p2.Name = "name2";
p2.Age = 20;
dic.Add(p2, "222");
if (dic.ContainsKey(p1))
{
Console.WriteLine("Contains");
}
else
{
Console.WriteLine("Not Contains");
}
}
}
class Person
{
private object parent;
public object Parent
{
get { return parent; }
set { parent = value; }
}
private int id;
public int Id
{
get { return id; }
set { id = value; }
}
private string name;
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public override int GetHashCode()
{
Console.WriteLine("In GetHashCode");
// Random num = new Random();
// int a = num.Next(1,100);
int hashCode = (this.Id == 0 || this.Id == null) ? 0 : this.Id.GetHashCode();
if (this.parent != null)
{
hashCode = 31 * hashCode + this.parent.GetHashCode();
}
return hashCode;
}
public override bool Equals(object obj)
{
Console.WriteLine("Equal 被执行");
if (obj == null || GetType() != obj.GetType())
{
return false;
}
return this.Id == (obj as Person).Id && this.Name == (obj as Person).Name;
}
}
}
在执行 dic.Add(p2, "222"); 时候除了会调用GetHashCode外,还会调用Equals方法
在执行if (dic.ContainsKey(p1))时,会先调用p1的GetHashCode方法,再调Equals方法。 这次会调用两次Equals方法,因为这个时候p1 和 p2在 dic集合里面的HashCode都是一样的。 第一次会让传入的obj和p2进行比较,然后会和p1 和 obj进行比较,最终输出Contains
Java 中这块的原理和C#相同