1、有一个类Person,有两个字段age和name,我重写Object类的equal方法来比较两个对象的age和name是否相等,
但是不重写hashCode。
package com.hash; public class Person {
private Integer age; private String name; public Person() {
super();
} public Person(Integer age, String name) {
super();
this.age = age;
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
} }
场景类
Person p1 = new Person(21,"tom");
Person p2 = new Person(21,"tom");
System.out.println(p1.equals(p2));
这样比较发现打印出来是true。然后执行下面的代码:
HashMap<Person,Integer> hp = new HashMap<Person,Integer>();
hp.put(p1, 10);
System.out.println(hp.get(p2));
发现打印出来是null,原因分析:
因这p1和p2只是逻辑上相等,但是它们的hashCode不相等,而hashMap往里面put对象的时
候,先获取key的hashcode,再往hash表中存数据
Person类没有重写hashCode方法,所以默认使用父类Object类的hashCode方法,是根据内存算的hashCode
,而p1和p2是在堆上new出的两个对象,二者的内存地址肯定不等,所以hashCode肯定不等,所以获取出来是null
要解决这个问题,只有重写hashCode方法,以确保当两个对象相同时,二者的hashCode必须相同
@Override
public int hashCode(){
Integer prime = 31;
return prime*age.hashCode() + prime*name.hashCode();
}
重写hashCode方法后,再执行,发现打印出了10
2、
如果两个对象相同,那么二者hashCode必定相同,而hashCode相同,对象却不一定相同,因为散列函数计算hashCode的时候
可能会发生碰撞,如
hash类,我在这个类的hashCode方法里计算hashCode时,只是让age和name相加,这种hash算法,碰撞的机率非常大
package com.hash; public class Hash {
private Integer age ; private Integer name; public Hash(Integer age, Integer name) {
super();
this.age = age;
this.name = name;
} public Hash() {
super();
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public Integer getName() {
return name;
} public void setName(Integer name) {
this.name = name;
} @Override
public int hashCode() {
final int prime = 31;
return prime*age+prime*name;
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Hash other = (Hash) obj;
if (age == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
} }
场景类
//这就是hashCode产生碰撞,二者hashCode相同,而对象并不相等
Hash ha1 = new Hash(11,12);
Hash ha2 = new Hash(12,11); System.out.println(ha1.equals(ha2));
System.out.println("h1 hashCode="+ha1.hashCode()+",h2 hashCode="+ha2.hashCode());
虽然两个对象的hashCode相等,但是两个对象并不相等。
综上
(1)如果重写equal方法,则必须重写hashCode方法。
(2)两个对象相等,则二者hashCode必然相等。
(3)两个对象的hashCode相等,两个对象未必相等,因为计算的hashCode可能会碰撞。