一,HashCode的作用
什么是hashCode:由对象,导出的一个整型值。
作用:为了提供查找的快捷性,用于在散列结构中,存储对象在Hash表中的地址。
二,重写了equals()方法,为何要重写hashcode()方法?
hashcode的源码说明,hashcode要满足以下条件:
<ul>
* <li>Whenever it is invoked on the same object more than once during
* an execution of a Java application, the {@code hashCode} method
* must consistently return the same integer, provided no information
* used in {@code equals} comparisons on the object is modified.
* This integer need not remain consistent from one execution of an
* application to another execution of the same application.
* <li>If two objects are equal according to the {@code equals(Object)}
* method, then calling the {@code hashCode} method on each of
* the two objects must produce the same integer result.
* <li>It is <em>not</em> required that if two objects are unequal
* according to the {@link java.lang.Object#equals(java.lang.Object)}
* method, then calling the {@code hashCode} method on each of the
* two objects must produce distinct integer results. However, the
* programmer should be aware that producing distinct integer results
* for unequal objects may improve the performance of hash tables.
* </ul>
1. 在java应用程序运行时,无论何时多次调用同一个对象时的hsahCode()方法,这个对象的hashCode()方法的返回值必须是相同的一个int值
2. 如果两个对象equals()返回值为true,则他们的hashCode()也必须返回相同的int值
3. 如果两个对象equals()返回值为false,则他们的hashCode()返回值也必须不同
举个例子:
public class Test {
public static void main(String[] args) {
String string = new String("a");
String string2 = new String("a");
System.out.println("内存地址比较结果:"+(string == string2));
System.out.println("值比较结果"+string.equals(string2));
}
}
输出结果:
内存地址比较结果:false
值比较结果true
分析:由于String重写了equals方法,可以看到值equals方法的 比较结果为true;而使用==比较,是比较内存地址,显然是两个不同的对象,也就有不同的地址,如果不重写hashcode方法,那么hashcode的值,也将会是默认值:内存地址。这时候,hashcode的值就不相等了,这时候,就不符合上述第二条规则。
三,拓展:为何String类型hashcode 计算式,选择31?
先看看源码:
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
直接原因吧:
1,JVM优化,31 = (2<<5)-1,JVM做了这个计算的优化,效率高。
2,31 为素数,可以减少冲突
3,31数字不是很大,也不是很小,可以减少冲突,并且不会溢出。
参考博客:https://www.cnblogs.com/nullllun/p/8350178.html
四,重写一个类的equals和hashcode方法示例:
package com.blog.spring.test;
public class Person {
private String name;
private int age;
@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 != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
}