问题

为什么在重写equals()方法的同时,必须重写hashCode()方法?

解答

在《每天一道Java题[2]》中,已经对hashCode()能否判断两个对象是否相等做出了解释。equals()方法与hashCode()方法的关系如下:

  1. 如果两个对象的hashCode()返回值不一样,则equals()返回的结果必为false。
  2. 如果两个对象的hashCode()返回值一样的时候,equals()返回的结果未知。
  3. 如果两个对象的equals()返回的结果为true,则两个对象的hashCode()返回值必定相等。
  4. 如果两个对象的equals()返回的结果为false,则两个对象的hashCode()返回值可能不同也可能相同。

可以看出,equals()与hashCode()有着千丝万缕的关系。简单的说,如果只重写了equals(),没有重写hashCode()的话,因为hashCode()主要用于散列的集合,这就会造成,当使用equals()为true的两个相当的对象作为散列集合中的key时,会得出不一样的结果,这其中原因就是他们的hashCode()返回值不同。

看下面一个例子:

package me.huangzijian;

import java.util.HashMap;

public class EqualsAndHashCode {

    private String name;
private int num;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public EqualsAndHashCode(String name, int num){
this.name = name;
this.num = num;
}
@Override
public boolean equals(Object obj) {
if(this.name.equals(((EqualsAndHashCode)obj).getName())&&this.num==((EqualsAndHashCode)obj).getNum()){
return true;
}
else{
return false;
}
}
public static void main(String[] args) {
EqualsAndHashCode equalsAndHashCode1 = new EqualsAndHashCode("a", 1);
System.out.println("equalsAndHashCode1's hashCode is: " + equalsAndHashCode1.hashCode());
HashMap<EqualsAndHashCode, Integer> hashMap = new HashMap<EqualsAndHashCode, Integer>();
hashMap.put(equalsAndHashCode1, 1);
EqualsAndHashCode equalsAndHashCode2 = new EqualsAndHashCode("a", 1);
System.out.println("equalsAndHashCode2's hashCode is: " + equalsAndHashCode2.hashCode());
System.out.println("equalsAndHashCode1.equals(equalsAndHashCode2) is: " + equalsAndHashCode1.equals(equalsAndHashCode2));
System.out.println(hashMap.get(equalsAndHashCode2));
}
}

输出的结果:

equalsAndHashCode1's hashCode is: 1712811212
equalsAndHashCode2's hashCode is: 1508661727
equalsAndHashCode1.equals(equalsAndHashCode2) is: true
null

从中可以看到,equalsAndHashCode1与equalsAndHashCode2的equals()为true,但hashCode()返回值不一样,这就违背了一开始描述的equals()与hashCode()的关系了。而且也可以看出,在HashMap中,也获取不出相同key值(equalsAndHashCode1与equalsAndHashCode2的equals()值为true,则认为是相同的对象)的value值了。

引用

对于hashCode()与equals()之间的关系,也可以参考《Effective Java》一书中的描述:

  • 在程序执行期间,只要equals方法的比较操作用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法必须始终如一地返回同一个整数。
  • 如果两个对象根据equals方法比较是相等的,那么调用两个对象的hashCode方法必须返回相同的整数结果。
  • 如果两个对象根据equals方法比较是不等的,则hashCode方法不一定得返回不同的整数。

每天一道Java题[3]的更多相关文章

  1. 每天一道Java题[11]

    题目 synchronized怎么实现线程同步?请修改<每天一道Java题[10]>中的MyRunnableThread类以解决三个线程都获取到10的问题. 解答 方法一: 采用synch ...

  2. 每天一道Java题[4]

    问题 怎么将字符串转换为int? 解答 此题看似简单,但经常出现在笔试等地方,由于大家习惯了用IDE,有什么还真未必能写出来.通常都是parseInt()方法进行转换,如下: Int n = Inte ...

  3. 每天一道Java题[6]

    题目 String字符串怎么转换为Date,Date又怎么转换成String字符串 解答 String->Date 主要用到类SimpleDateFormat及其抽象父类DateFormat中的 ...

  4. 每天一道Java题[9]

    题目 native关键字的作用是什么? 解答 首先,需了解JNI(Java Native Interface),它是连接Java平台与本地C代码的一个API. 其次,用native关键字声明的方法,是 ...

  5. 每天一道Java题[1]

    问题:char[]与String相比,有什么优胜的地方? 回答: 针对安全保密高的信息,char[]比String做得更好.因为String是不可变得,即使你修改原先的变量,实际上也是在内存中新建一个 ...

  6. 每天一道Java题[2]

    问题 可以直接根据hashCode()方法产生的值判断两个对象是否相等吗? 解答 不能!根据Wikipedia(https://en.wikipedia.org/wiki/Java_hashCode( ...

  7. 每天一道Java题[5]

    题目 String.StringBuilder.StringBuffer有什么异同? 解答 相同点:String.StringBuilder.StringBuffer都可以用来存储字符串. 不同点: ...

  8. 每天一道Java题[7]

    题目 什么是REST原则,请解释RESTful架构,以及其设计思想? 解答 REST,全称为Representation State Transfer,是一种互联网软件的架构原则.凡是满足REST原则 ...

  9. 每天一道Java题[10]

    题目 阐述创建线程最常用的两种方法及其对比. 解答 方法一:继承Thread类实现 步骤: 创建Thread类的子类,如MyThread. 重写Thread类的run()方法. 实例化MyThread ...

随机推荐

  1. Zookeeper-3.4.9 集群搭建

    这里用了三台主机,系统为CentOS7 1.修改hosts #vim /etc/hosts 172.50.0.31 node1 172.50.0.34 node2 172.50.0.37 node3 ...

  2. [C++]STL容器Vector的内存释放

    直接抛出两句话,说明到底应该如何释放Vector占用的内存. “vector的clear不影响capacity,你应该swap一个空的vector.” <Effective STL>中的“ ...

  3. 面试题(一)—Java基础(上)

    1.面向对象的三大特征 (1)封装      封装性指的是隐藏了对象的属性和实现细节,对外仅提供公共的访问方式.      好处: 将变化隔离,提供复用性和安全性. (2)继承      提高代码的复 ...

  4. Android ShellUtils

    Android中执行Shell命令的工具类 public class ShellUtils { public static final String COMMAND_SU = "su&quo ...

  5. 04 Feasibility of Learning

    机器学习是设计算法A,在假设集合H里,根据给定数据集D,选出与实际模式f最为相近的假设g(g可能与f相同,也可能不同). 那什么情况下学习是可行的?即保证g和f是相似的. 1.数据集内的表现g约等于f ...

  6. 分离你的spring配置文件,让结构更清晰

    前言 接着上一篇的,这次框架的改变也成功分离了spring的配置文件. 以前,spring的配置文件从一开始的一点,到后面的逐渐变多,慢慢的,在一个spring的配置文件中就包含了好几块不同的bean ...

  7. (function($){….})(jQuery)一种js插件写法

    我们先看第一个括号里边的内容:function($){….},这不就是一个匿名的函数吗?但是它的形参比较奇怪,是$,这里主要是为了不与其它的库冲突. 这样我们就比较容易理解第一个括号内的内容就是定义了 ...

  8. 谁用光了磁盘?Docker System命令详解

    译者按: Docker镜像,容器,数据卷以及网络都会占用主机的磁盘空间,这样的话,磁盘很容易就会被用完.这篇博客介绍了一个简单的解决方案 - Docker System命令. 原文: What's e ...

  9. URL传中文参数导致乱码的解决方案之encodeURI

    通过URL传中文参数时,在服务端后台获取到的值往往会出现乱码问题,解决方案有很多种,本文主要介绍如何通过encodeURI来解决中文乱码问题: first:前端传递参数的时候需要对中文参数进行两次en ...

  10. git提交如何忽略某些文件

    在使用git对项目进行版本管理的时候,我们总有一些不需要提交到版本库里的文件和文件夹,这个时候我们就需要让git自动忽略掉一下文件. 使用.gitignore忽略文件 为了让git忽略指定的文件和文件 ...