HashCode和Equals,看我理解的对嘛?

39 阅读4分钟

又到了金三银四,准备了几天Java八股文,发现自己差挺多,死记不是个办法,最近在读《认知觉醒》,里面提到关于知识的稳固其实还是在于输出,所以我想着趁着掘金有活动,我自己也做个记录,至于为什么选择这个标题,是因为这个内容我背了好多次,想通过自己的理解写下来,看看我到底是理解了多少,虽然简单,希望大家不吝批评和指正,那对我就很有帮助了。

hashcode和equals是java中,object类的默认方法,由于object是基类,所以我们使用的类也就有这个方法,看源码注释如下:

/**
 * Returns a hash code value for the object. This method is
 * supported for the benefit of hash tables such as those provided by
 * {@link java.util.HashMap}.
 * <p>
 * The general contract of {@code hashCode} is:
 * <ul>
 * <li>Whenever it is invoked on the same object more than once during
 *     an execution of a Java application, the {@code hashCode} method
 *     must consistently return the same integer, provided no information
 *     used in {@code 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.
 * <li>If two objects are equal according to the {@code equals(Object)}
 *     method, then calling the {@code hashCode} method on each of
 *     the two objects must produce the same integer result.
 * <li>It is <em>not</em> required that if two objects are unequal
 *     according to the {@link java.lang.Object#equals(java.lang.Object)}
 *     method, then calling the {@code 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.
 * </ul>
 * <p>
 * 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&trade; programming language.)
 *
 * @return  a hash code value for this object.
 * @see     java.lang.Object#equals(java.lang.Object)
 * @see     java.lang.System#identityHashCode
 */

使用Idea的通义插件翻译了下,如下: 以上是Java中Object类的hashCode方法的文档注释,解释了hashCode方法的契约和实现要求。hashCode方法用于返回对象的哈希码值,主要用于支持哈希表(如HashMap)。其核心要求包括:同一对象多次调用hashCode应返回相同值;若两个对象equals相等,则它们的hashCode也必须相等;但hashCode不要求不同对象返回不同值,不过不同对象的哈希码不同有助于提高哈希表性能。

从以上这段文字,我们知道了同一对象多次调用hashCode应返回相同值;若两个对象equals相等,则它们的hashCode也必须相等,那这是为什么呢?

这里面提到了equals,那我们先看看equals的方法内部,很简单。

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

  我们知道默认的==就是比较地址,但是类生成的每个实例都是不一样的,因为内存地址是不一样的,所以如果不重写,实际每个实例之间都是不同的。

但是我们代码的逻辑有时候不一定是说地址不一样,实例就不一样,比如两个字符串,都是new String("hello world"),如果String未重写这2个方法,那么地址肯定不一样,所以比较的话也就不相等,但是我们实际应用时是想让这2个比较起来是相等的,所以重写equals方法,此时比较就不是基于地址,而是基于内容,既然重写了equals,如果不重写hashcode就会造成逻辑不一致,因为两个一样的实例,其hashcode应该是相等的,所以也得重写hashcode方法使其保持一致。这就符合了这句话:若两个对象equals相等,则它们的hashCode也必须相等;

再看下一句话,说不要求不同的对象返回不同的hashcode,因为hashcode是经过一系列的计算得出来的,如果重写了hashcode,难免会出现计算出相同的结果,但是这不代表这2个对象就是相同的,所以重写hashcode不强制要求重写equals。

但是又提到一句话说,不过不同对象的哈希码不同有助于提高哈希表性能,我们假设个极端情况,如果不同的对象都是同一个哈希码,那么假如从hashmap中取数据,此时的时间复杂度就是O(n)了,而不是一般情况下的O(log n),甚至另一个极端情况下,如果不存在hash冲突,此时的时间复杂度就是O(1)了。

以上就是我的理解,如有补充,欢迎大家评论区指出。感谢~