为什么使用HashMap需要重写hashcode和equals方法

编程入门 行业动态 更新时间:2024-10-28 00:24:18

为什么使用HashMap需要<a href=https://www.elefans.com/category/jswz/34/1769232.html style=重写hashcode和equals方法"/>

为什么使用HashMap需要重写hashcode和equals方法

# 问题

当我们使用equals和hashcode方法时,我们需要考虑什么问题?

# 最佳答案

就像《effective java》这本书中提到,尽管java.lang.Object是一个具体的类,但是这个类的主要功能就是用于扩展(非final方法可被覆盖),因此,它所有的非final方法都有明确的约定。所有的类在覆盖Object的方式时,都有义务遵守这些约定。否则,其它依赖这些约定的类就无法正常运转,比如我们经常提到的HashMap、HashSet等等。

接着,咱们看看本题目中所提到的两个方法:

hashCode()

我们可以主要到这个方法由native关键字修饰,因此,它底层由c/c++来实现(符合JNI编程规范),关于具体的实现,这里不做过多的讨论,感兴趣的可以去看看openjdk源码。

同时,javadoc文档中提到:如果一个对象提供给equals做比较的信息没有被修改的话,该对象多次调用hashCode()方法,该方法必须始终如一返回同一个integer。

equals()

从Object的源码中,我们可以看出它是对两个对象的地址值进行的比较(即比较引用是否相同)。如果你看过String 、Math、Integer、Double等这些包装类的equals()方法源码时,会发现,它们已经覆盖了object类的equals()方法。

它们已不再符合地址比较,它们之间符合等价关系(自反性,对等性,传递性,一致性),另外,它们必须是一致的(如果未修改对象,则它必须保持返回相同的值)。此外,o.equals(null)必须始终返回false。

因此,这两个方法之间的关系,应该是:

如果两个对象相同,那么它们的hashCode值一定要相同;

如果两个对象的hashCode相同,它们并不一定相同(这里说的对象相同指的是用eqauls方法比较)。   

equals()相等的两个对象,hashcode()一定相等;equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。

Object规范

这里需要再次提醒一下,也是在《effective java》这本书(见第9条)中曾提到过,也是本题的答案:equal和hashcode方法必须同时重写,缺一不可。

怎么重写呢?

使用类的同组属性去重写equals和hashcode方法。

这里,第三方的组件commons-lang3给我们提供了两个工具类,分别是 EqualsBuilder 和 HashCodeBuilder方法,见下面的例子:

public class Person {    private String name;    private int age;    // ...    @Override    public int hashCode() {        return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers            // if deriving: appendSuper(super.hashCode()).            append(name).            append(age).            toHashCode();    }    @Override    public boolean equals(Object obj) {       if (!(obj instanceof Person))            return false;        if (obj == this)            return true;        Person rhs = (Person) obj;        return new EqualsBuilder().            // if deriving: appendSuper(super.equals(obj)).            append(name, rhs.name).            append(age, rhs.age).            isEquals();    }}

记住,使用基于hashcode的Collection或Map(例如HashSet,LinkedHashSet,HashMap,Hashtable或WeakHashMap)时,请确保放入元素(key)的hashcode在集合中一直保持不变。

我记得之前有个同学,跟我提过,他在使用hibernate的过程中,发现hibernate经常会使用set集合来保持相关对象。他有次只重写了equals方法,而没有重写hashcode方法,当存入的元素越来越多时,发现性能越来越差,为啥呢?

后来,跟踪发现,原来是set在进行判重时,会有大量的元素的hashcode方法返回的值一样,因此会调用equals方法进行比较,降低了性能。重写了hashcode方法,就好了。

比如,这样写:

public int hashCode(){     return 1; //等价于hashcode无效  } 

你可以去尝试一下。

今晚,就写到这里,记得转发,给我补充下一直写下去的燃料~~~

参考:http : //stackoverflow/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java

 往期推荐 

🔗

  • SO面试题06:如何测试数组是否包含某些值?
  • 小实验:一次性把几百万数据放入内存,系统会撑爆吗?
  • 我的奇葩面试经历:HR竟然主动提价,比预期高了5K,我一脸懵逼...

点击

更多推荐

为什么使用HashMap需要重写hashcode和equals方法

本文发布于:2024-02-27 12:40:47,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1706550.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:重写   方法   HashMap   equals   hashcode

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!