java中hashCode() 和 equals()方法的解析

时间:2021-02-23 16:11:54

本文很多都参考了别的大神的文章,这是我第一次写博客。引用的文章在更多文章那里可以找到,感谢他提供的博文,同时做出道歉


最近,学到java集合框架时,接触到了两个让我傻傻分不清楚的两个方法:hashcode()和 equals()。在set 和 map中,往里面添加自定义类时,自定义的类都要重写了hashcode()和 equals(),到底为什么呢?
equals(Object obj)和hashcode()这两个方法是在Object类中定义的,所以每一个类都有这两个方法。 
equals(Object obj)方法用来判断两个对象是否相同,如果相同则返回true,否则返回false。 实现代码如下:

<span style="font-size:18px;">public boolean equals(Object obj) { 
return (this == obj);
} </span>
这个方法是对两个对象的地址值进行的比较(即比较引用是否相同),但是,String 、Math、还有Integer、Double。。。。等这些封装类已经覆盖了父类的equals()方法,它们是对类内容的比较而不是地址的比较了。例如下面的String的内部方法:

<span style="font-size:18px;">public boolean equals(Object anObject) { 
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
</span>


Java语言对equals()的要求如下,这些要求是必须遵循的: 
• 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。 
• 反射性:x.equals(x)必须返回是“true”。 
• 类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。 
• 还有一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。 
• 任何情况下,x.equals(null),永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”。
hashcode()方法的官方解析为:

官方定义
  1. hashcode方法返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表。   
  2.   
  3. hashCode 的常规协定是:   
  4. 在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。   
  5. 如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。   
  6. 以下情况不 是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。   
  7. 实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)   
  8.   
  9. 当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。 


所以,equals()方法主要是用来判断对象是否相等的,而哈希码(hashcode)主要是用来查找的,根据百科,hashcode是它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。也有相同的情况,看程序员如何写哈希码的算法。

在实际的程序编写中,要考虑四个问题:

第一:当哈希码相同,而equals()返回值为false

第二:当哈希码相同,而equals()返回值为true

第三:当哈希码不同,而equals()返回值为false

第四:当哈希码不同,而equals()返回值为true

分别代表什么?

当我们将某个对象存到set中时,如果该对象的属性参与了hashcode的计算,那么以后就不能修改该对象参与hashcode计算的那些属性了,否则会引起意向不到的错误的。正如测试中,不能够移除stu1对象。
总结:

1、equals方法用于比较对象的内容是否相等(覆盖以后)

2、hashcode方法只有在集合中用到

3、当覆盖了equals方法时,比较对象是否相等将通过覆盖后的equals方法进行比较(判断对象的内容是否相等)。

4、将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。

5、将元素放入集合的流程图:

java中hashCode() 和 equals()方法的解析