重写hashcode和equals怎么重写
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重写hashcode和equals怎么重写相关的知识,希望对你有一定的参考价值。
参考技术A 当原对象.equals(新对象)等于true时,两者的hashcode却是不一样的,由此将产生了理解的不一致,如在存储散列集合时(如Set类),将会存储了两个值一样的对象,导致混淆,因此,就也需要重写hashcode()举例说明:import
java.util.*;
public
class
HelloWorld
public
static
void
main(String[]
args)
/*
Collection
c
=
new
HashSet();
c.add("hello");
c.add(new
Name("f1","l1"));
c.add(new
Integer(100));
c.remove("hello");
c.remove(new
Integer(100));
System.out.println(c.remove(new
Name("f1","l1")));
*/
Name
n1
=
new
Name("01");
Name
n2
=
new
Name("01");
Collection
c
=
new
HashSet();
c.add(n1);
System.out.println("------------");
c.add(n2);
System.out.println("------------");
System.out.println(n1.equals(n2));
System.out.println("------------");
System.out.println(n1.hashCode());
System.out.println(n2.hashCode());
System.out.println(c);
class
Name
private
String
id;
public
Name(String
id)
this.id
=
id;
public
String
toString()
return
this.id;
public
boolean
equals(Object
obj)
if
(obj
instanceof
Name)
Name
name
=
(Name)
obj;
System.out.println("equal"+
name.id);
return
(id.equals(name.id));
return
super.equals(obj);
public
int
hashCode()
Name
name
=
(Name)
this;
System.out.println("Hash"
+
name.id);
return
id.hashCode();
就这个程序进行分析,在第一次添加时,调用了hashcode()方法,将hashcode存入对象中,第二次也一样,然后对hashcode进行比较。hashcode也只用于HashSet/HashMap/Hashtable类存储数据,所以会用于比较,需要重写
总结,自定义类要重写equals方法来进行等值比较,自定义类要重写compareTo方法来进行不同对象大小的比较,重写hashcode方法为了将数据存入HashSet/HashMap/Hashtable类时进行比较
重写equals就必须重写hashCode的原理分析
不被重写(原生Object)的hashCode和equals是什么样的?
不被重写(原生)的hashCode值是根据内存地址换算出来的一个值。
不被重写(原生)的equals方法是严格判断一个对象是否相等的方法(object1 == object2)。
为什么需要重写equals和hashCode方法?
在我们的业务系统中判断对象时有时候需要的不是一种严格意义上的相等,而是一种业务上的对象相等。在这种情况下,原生的equals方法就不能满足我们的需求了。
所以这个时候我们需要重写equals方法,来满足我们的业务系统上的需求。
所以这个时候我们需要重写equals方法,来满足我们的业务系统上的需求。
那么为什么在重写equals方法的时候需要重写hashCode方法呢?我们先来看一下Object.hashCode的通用约定(摘自《Effective Java》第45页)
1.在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,那么,对该对象调用hashCode方法多次,它必须始终如一地返回 同一个整数。在同一个应用程序的多次执行过程中,这个整数可以不同,即这个应用程序这次执行返回的整数与下一次执行返回的整数可以不一致。
2.如果两个对象根据equals(Object)方法是相等的,那么调用这两个对象中任一个对象的hashCode方法必须产生同样的整数结果。
3.如果两个对象根据equals(Object)方法是不相等的,那么调用这两个对象中任一个对象的hashCode方法,不要求必须产生不同的整数结果。然而,程序员应该意识到这样的事实,对于不相等的对象产生截然不同的整数结果,有可能提高散列表(hash table)的性能。
即:
两个对象相等,hashcode一定相等
两个对象不等,hashcode不一定不等
hashcode相等,两个对象不一定相等
hashcode不等,两个对象一定不等
如果只重写了equals而没有重写hashCode
如果只重写了equals方法而没有重写hashCode方法的话,则会违反约定的第二条:相等的对象必须具有相等的散列码(hashCode)。
同时对于HashSet和HashMap这些基于散列值(hash)实现的类。HashMap的底层处理机制是以数组的方法保存放入的数据的(Node<K,V>[] table),其中的关键是数组下标的处理。数组的下标是根据传入的元素hashCode方法的返回值再和特定的值异或决定的。如果该数组位置上已经有放入的值了,且传入的键值相等则不处理,若不相等则覆盖原来的值,如果数组位置没有条目,则插入,并加入到相应的链表中。检查键是否存在也是根据hashCode值来确定的。所以如果不重写hashCode的话,可能导致HashSet、HashMap不能正常的运作、
如果我们将某个自定义对象存到HashMap或者HashSet及其类似实现类中的时候,如果该对象的属性参与了hashCode的计算,那么就不能修改该对象参数hashCode计算的属性了。有可能会移除不了元素,导致内存泄漏。
以上是关于重写hashcode和equals怎么重写的主要内容,如果未能解决你的问题,请参考以下文章
谈谈HashSet的存储原理及为什么重写equals必须重写hashcode方法
JAVA中重写equals方法为啥要重写hashcode方法说明