为什么重写equals方法时必须重写hashCode方法

介绍两个方法作用
object中equals和hashcode方法

/** 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.
 * 注意,通常有必要重写{@code hashCode} 方法,以便维护 hashCode方法的通用契约,
 * 它声明相同的对象必须具有相同的散列码。
 */
public boolean equals(Object obj) {
    
    
     return (this == obj);
 }
/*  
 * As much as is reasonably practical, the hashCode method defined by
 * class {@code 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.)
 * 定义的hashCode方法具有相当的实用性class {@code Object}确实返回不同的整数
 * 对象
 *
 * @return  a hash code value for this object.
 * @see     java.lang.Object#equals(java.lang.Object)
 * @see     java.lang.System#identityHashCode
 */
public native int hashCode();

equals方法:当我们将equals方法重写后有必要将hashCode方法也重写,这样做才能保证不违背hashCode方法中相同对象必须有相同哈希值的约定。

hashCode方法:将对象的地址值映为integer类型的哈希值

实验分析

package com.geekmice.onetomany.hashcode;

import java.util.HashSet;

public class OverrideTest {
    
    
    public static void main(String[] args) {
    
    
        Student s1 = new Student();
        s1.setAge(new Integer(18));
        s1.setUserName("小红");
        Student s2 = new Student();
        s2.setAge(new Integer(18));
        s2.setUserName("小红");
        System.out.println(s1.equals(s2));
        HashSet<Student> studentHashSet1 = new HashSet<>();
        studentHashSet1.add(s1);
        HashSet<Student> studentHashSet2 = new HashSet<>();
        studentHashSet2.add(s2);
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
        // 重写equals,hashcode方法=>true
        System.out.println(studentHashSet1.equals(studentHashSet2));
        // 只是重写equals => false
        /**
         * 分析:由于Student对象没有重写hashcode方法,使用的是父类Object中默认hashcode方法
         * 它这个方法是根据对应地址情况进行计算,由于s1,s2地址不一致,hashcode不一样
         */
        System.out.println(studentHashSet1.equals(studentHashSet2));
    }
}

结论

equals方法与hashCode方法根本就是配套使用的。对于任何一个对象,不论是使用继承自Object的equals方法还是重写equals方法。hashCode方法实际上必须要完成的一件事情就是,为该equals方法认定为相同的对象返回相同的哈希值。如果只重写equals方法没有重写hashCode方法,就会导致equals认定相同的对象却拥有不同的哈希值。

Object类中的equals方法区分两个对象的做法是比较地址值,即使用==。如果根据业务需求改写了equals方法的实现,那么也应当同时改写hashCode方法的实现。否则hashCode方法依然返回的是依据Object类中的依据地址值得到的integer哈希值

hashset去重功能失效

猜你喜欢

转载自blog.csdn.net/greek7777/article/details/126354743