那具体如何正确地覆盖equals()呢?《Effective JAVA》里面给出了方法,套路是一样的,其目标是保证:自反性、对称性、一致性。总之,对于上面的Address类而言,可以这样:
@Override
public boolean equals(Object obj) {
if(obj == this)
return true;
if(!(obj instanceof Address))
return false;
Address address = (Address)obj;
return address.getProvince().equals(province) && address.getCity().equals(city);
}
第8行从表明如果两个Address的 province 和 city 相同,那这两个Address就是相同的,这样equals方法就会返回true了。(不考虑字符串大小写问题)
覆盖完了equals(),接下来就是 覆盖hashCode()了。覆盖hashCode()的目标是:
如果两个对象 address1.equals(address2) 返回 false,那么 address1.hashCode() 最好 不等于 address2.hashCode()
当然,没有超级完美的hashCode(),如果相等了,那么当 hashMap.put(address1,value1) hashMap.put(address2,value2) 就会put到同一个 hashmap的同一个槽下了。
重写了equals和hashCode的Address类如下:
public class Address { private String province; private String city; public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public Address() {} public Address(String province, String city) {this.province = province; this.city = city;} @Override public boolean equals(Object obj) { if(obj == this) return true; if(!(obj instanceof Address)) return false; Address address = (Address)obj; return address.getProvince().equals(province) && address.getCity().equals(city); } @Override public int hashCode() { int result = 17; result += 31 * province.hashCode(); result += 31 * city.hashCode(); return result; } }
测试类如下:
import java.util.HashMap; import java.util.Map; public class TestAddress { public static void main(String[] args) { Address address1 = new Address("广东","广州"); Address address2 = new Address("广东", "广州"); System.out.println(address1 == address2);//false System.out.println(address1.equals(address2));//true System.out.println(address1.hashCode() == address2.hashCode());//true Address diff1 = new Address("四川","成都"); Address diff2 = new Address("四川","绵阳"); System.out.println(diff1 == diff2);//false System.out.println(diff1.equals(diff2));//false System.out.println(diff1.hashCode() == diff2.hashCode());//false Map<Address, Integer> hashMap = new HashMap<Address, Integer>(); hashMap.put(address1, 1); hashMap.put(address2, 2);//address2的hashCode 和 address1 相同,因此 put 方法会覆盖 address1 对应的 Value值1 System.out.println(hashMap.get(address1));//2 System.out.println(hashMap.get(address2));//2 hashMap.put(diff1, 1); hashMap.put(diff2, 2); System.out.println(hashMap.get(diff1));//1 System.out.println(hashMap.get(diff2));//2 } }