说重写equals必须跟着重写hashCode,即如果x.equals(y)返回true,那么x.hashCode()也要等于y.hashCode()。
假设比较员工的name,很好理解,当name相同的时候,hashCode也相同,因为String有自己的hashCode计算方法,是按照内容返回的。
但是如成员变量属于某个其他的类,而这个类没有自己的hashCode方法,那么只能返回Object的默认hashCode计算结果,即对象的存储地址。
此时x.equals(y)可以为true,(假设x和y是Date类的对象,表示入职时间)。但存储地址肯定不一样啊。这怎么说?
java中的数据类型,可分为两类:
1.基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean
他们之间的比较,应用双等号(==),比较的是他们的值。
2.复合数据类型(类)
当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。 JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地 址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号(==)进行比较的,所以比较后的结果跟双等号(==)的结果相同。
如果两个对象根据equals()方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。
如果两个对象根据equals()方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode方法,则不一定要产生相同的整数结果
equals判断相等,hashcode必须相等
equals不等,hashcode可以相等,可以不相等。
之所以区分equals和hashcode,前者为了精确比较,后者为了快速比较(如果hash不相等,没有必要进一步比较了,肯定不等);同时利用hash,给对象的列表编排索引。
考虑两个满足以上规则的极端的情况:
(1)equals只要不相等,hashcode一定不相等。为了达成这一点,计算hashcode的时间成本和完整比较两个对象的时间成本一致。
(2)无论怎么样的两个对象,hashcode都返回一个常数。这么做符合规则,但是会使得hasttable的搜索速度趋近于线性搜索。
所以,在满足规则的前提下,hashcode的算法应该避免以上两个极端,至于具体用什么算法,这个倒不一定。