Java正确地自定义比较对象—如何重写equals方法和hashCode方法

在实际应用中经常会比较两个对象是否相等,比如下面的Address类,它有两个属性:String province 和 String city。

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;}

}

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));//false
System.out.println(address1.hashCode() == address2.hashCode());//false
}
}

    public boolean equals(Object obj) {
        return (this == obj);
    }

JDK中对该方法的注释如下:也就是说:Object类的equals方法 是通过 == 来比较两个对象是否相等的,也即根据 对象x引用 和 对象y 的引用是否指向内存中的同一个地址 来判断 对象x 和 对象y 是否相等。

     * The {@code equals} method for class {@code Object} implements
     * the most discriminating possible equivalence relation on objects;
     * that is, for any non-null reference values {@code x} and
     * {@code y}, this method returns {@code true} if and only
     * if {@code x} and {@code y} refer to the same object
     * ({@code x == y} has the value {@code true}).

   / * Note that it is generally necessary to override the {@code hashCode}
     * method whenever this method is overridden, so as to maintain the
     * general contract for the {@code hashCode} method, which states
     * that equal objects must have equal hash codes.
    */
    public boolean equals(Object obj) {
        return (this == obj);
    }

@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);
}

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
hashMap = new HashMap
(); 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 } }

最后,其实Eclipse里面为我们提供了自动 生成 equals和hashCode的方法,可参考:JAVA中equals方法与hashCode方法学习。自动生成的方法如下:(还是自动生成的更专业呀。。。。)

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((city == null) ? 0 : city.hashCode());
        result = prime * result + ((province == null) ? 0 : province.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;
        Address other = (Address) obj;
        if (city == null) {
            if (other.city != null)
                return false;
        } else if (!city.equals(other.city))
            return false;
        if (province == null) {
            if (other.province != null)
                return false;
        } else if (!province.equals(other.province))
            return false;
        return true;
    }

:http://www.linuxidc.com/Linux/2017-08/146154.htm