- 阿兵,你知道重写equals和hashCode吗?
- 害,那玩意儿我能不知道?重写equals的时候必须要重写hashCode方法。
- 那为啥呢?为啥俩就需要一起重写?
- 你来找茬的吧。
尴尬的一段对话,学JavaSE的时候记住了重写equals方法的时候还必须要重写hashCode方法,但是却一直不知道为什么,现在补上补上。
比较的时候equals就行了,为什么还需要hashCode?
首先equals与hashcode间的关系是这样的:
- 如果两个对象相同(即用equals比较返回true),那么它们的hashCode值一定要相同;
- 如果两个对象的hashCode相同,它们并不一定相同(即用equals比较返回false) 。
重写的目的: 由于为了提高程序的效率才实现了hashCode方法,先进行hashCode的比较,如果不同,那没就不必在进行equals的比较了,这样就大大减少了equals比较的次数,这对比需要比较的数量很大的效率提高是很明显的。
举例: 假设现在在维护一个无重复的List,当我们新插入一个元素的时候,应当先判断List中是否有这个元素。假定List中存放的是Person类,如下:
1 | class Person { |
我们每次插入的时候只需要利用equals方法,依次与List中的每个Person比较,判断Person.name是否相同;但是如果Person类的属性除了name,还有age、gender、weight等特别多的属性呢?
1 | class Person { |
每次比较都需要比较Person类中的各个属性,这无疑会让插入的操作效率十分低下。
而重写hashCode方法,根据Person实例中的属性特征利用特定的算法计算出hash值,并将其存放到hash值所指向的地址,而后面定义进来的数据只需要看自己对应的hash值地址上是否有值,如果有值说明可能是重复的元素,需要再调用equals方法进行比较;如果没有值则直接插入,这样就极大的减少了equals方法的调用次数,插入操作执行的效率大大提升。
示例:重写equals方法和hashCode方法(皆是IDEA自动生成)
1 | class Person { |
Object类中的equals和hashCode方法
Object.equals()方法,比较的是对象在内存中的地址。
1 | public boolean equals(Object obj) { |
Object.hashCode()方法,返回的是对象在内存中的地址。(别问,问就是自己run一下)
1 | public native int hashCode(); |
在源码中介绍到:
- 每当重写equals方法时,通常都需要重写hashCode方法,以便维护hashCode方法的一般约定,即相同的对象必须具有相同的哈希代码;
- 如果在Java应用程序的执行过程中对同一对象多次调用hashCode方法,那么hashCode方法必须始终返回相同整数,前提是没有修改对象的equals比较中使用的信息;
- 如果两个对象根据equals(Object)方法是相等的,那么调用这两个对象中任一个对象的hashCode方法必须产生同样的整数结果;
- 如果两个对象根据equals(Object)方法是不相等的,那么调用这两个对象中任一个对象的hashCode方法,不要求必须产生不同的整数结果。然而,程序员应该意识到这样的事实,对于不相等的对象产生截然不同的整数结果,有可能提高哈希表的性能。
最重要的是需要保证:两个对象根据equals方法是相等的,那么调用两个对象中任意的hashCode方法的值也必须相等。
总结:hashCode的引入目的是为了提高效率