在Java语言中,Object对象中包含一个equals和hashCode方法,其中hashCode方法是由JVM本地代码(native code)实现的,返回值是一个
有符号的32位整数,对象的hash值一般为用于在管理多个对象的数据结构中
用于提高性能而设计的,比如HashMap。有些语言的hash值就是这个对象在内存中的地址转化的整数,
但是java中的实现并不是这样。equals方法的实现很简单,就是利用==运算符比较两个对象的内存引用地址是否相等,当然,不是所有对象的比较都是比较内存,比如Integer,Long,Double等这些表示数字的类内部都对equals方法进行了重写,这些数值类equals比较的是数值大小。
Object类的equals&hashCode的实现:
public boolean equals(Object obj) { return (this == obj); } public native int hashCode();
Integer类的内部equals和hashCode的实现:
public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; } public int hashCode () { return value; }
关于hash值的一般性规约
- 对同一个对象多次调用hashCode方法,都应该始终如一的返回同一个值。
- 两对象相等,其hash值比较也应该相等(如果重写了对象的equals方法,那么对应的hashCode的实现也应该要重写以保证hash值也是相等的)
- 两对象不等,其hash值不要求也不等(但如果能不等,会提高程序性能)。
重写HashCode()和equals()
Employee e1 = new Employee(); Employee e2 = new Employee(); e1.setId(100); e2.setId(100); //Prints false in console System.out.println(e1.equals(e2)); // output: false
对于上面的代码,在具体的业务逻辑中我们通常希望比较的结果应该是:true,但是由于两个对象引用的地址不同,所以equals比较的结果是false,若希望e1和e2比较的结果是true,我们就需要重写equals方法
@override public boolean equals(object o) { if(o == null) { return false; } if (o == this) { return true; } if (getClass() != o.getClass()) { return false; } Employee e = (Employee) o; return (this.getId() == e.getId()); }
再看下面的例子:
Set<Employee> employees = new HashSet<Employee>(); employees.add(e1); employees.add(e2); System.out.println(employees); // output: two elements
我们期望的结果是:若equals比较相等的对象,放入HashSet或HashMap中也应该只能放入一个,但为什么会出现两个元素呢,因为两个对象的hashCode值是不一样的,所以HashSet认为是两个不同的元素。因此,若想得到期望的结果,需要重写hashCode方法:
@Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + getId(); return result; }
利用Eclipse的代码生成工具生成重写HashCode和equals的方法

生成的代码如下:
@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; } @Override public boolean equals(Object obj) { if (this == obj) return true ; if (obj == null) return false ; if (getClass() != obj.getClass()) return false ; HashCodeDemo1 other = (HashCodeDemo1) 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 ; }
注意事项:
- equals和hashCode方法一般需要同时重写
- 如果a.equals(b),那么也要保证a.hashCode() == b.hashCode()
- 尽量使用相同的属性来重写equals和hashCode方法,比如上述例子中两个重写方法中都是利用的id属性。
- 如果你使用ORM处理一些对象的话,你要确保在hashCode()和equals()对象中使用getter和setter而不是直接引用成员变量。因为在ORM中有的时候成员变量会被延时加载,这些变量只有当getter方法被调用的时候才真正可用。
参考: