判断相等重写equals和重写hashCode的原因

从开始学习编程,老师或者各种书上都说重写equals就要重新hashCode。但是为什么一定要重写hashCode呢?似乎直接重新equals方法,也是可以判断2个对象的相等。

其中equals与hashCode在Object中如下:

/**
Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by java.util.HashMap.
The general contract of hashCode is:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in 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.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
It is not required that if two objects are unequal according to the equals(Object) method, then calling the 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.
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the Java™ programming language.)
Returns:
a hash code value for this object.
See Also:
equals(Object), System.identityHashCode
**/ 
public native int hashCode();
    
/**
Indicates whether some other object is "equal to" this one.
The equals method implements an equivalence relation on non-null object references:
It is reflexive: for any non-null reference value x, x.equals(x) should return true.
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
For any non-null reference value x, x.equals(null) should return false.
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
Params:
obj – the reference object with which to compare.
Returns:
true if this object is the same as the obj argument; false otherwise.
See Also:
hashCode(), java.util.HashMap
**/
public boolean equals(Object obj) {
        return (this == obj);
    }

其中,对于hashCode:

返回对象的hash值,是为了像hashMap这类集合提供更好的支持

equals方法中相等,hashCode一定相等;

hashCode相等,equals方法不一定相等;

hashCode不相等,equals方法一定不相等;

从这里其实就可以看到,hashCode是java为了支持哈希表数据结构而提供的。如果不考虑哈希数据结构,那equals完全可以判断相等。

下面是一个Student类,重写了equals方法,把重写的hashCode方法注掉,因此使用的是Object中的native方法产生的hashCode.

public class Student {
    private String id;
    private String name;
    private int age;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

//    @Override
//    public int hashCode() {
//        return Objects.hash(name, age);
//    }
}

结果如下:

 只重写equals是可以判断两个对象是否相等的,前提是不使用哈希数据结构。

如果使用hashMap,hashSet时,因为对象hashCode不相等,判断是不同对象,就会都添加到key中。可以看到两个相等的对象添加到了hashMap中,这就造成了逻辑的混乱,对象比较相等,但是到了HashMap中就不相等了

 hashMap中先通过hashCode判断是否相等,不相等结果为false走其他判断逻辑

 在代码规范里对equals和hashCode有以下要求:

1.只要重写equals,就必须重写hashCode.

2.因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须要重写这2个方法。

3.如果自定义对象作为Map的键,那么就必须重写hashCode和equals.

说明:String已经重写了equals和hashCode方法,所以可以安心的用String对象作为key来使用

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值