【0】README

0.1)本文转自 core java volume 1, 旨在理清 equals + hashCode方法;


##**【1】equals方法**
**1.1)** Object中的 equals 方法用于检测一个对象是否等于另外一个对象;(在Object类中, 这个方法比较的是内存地址, 判断的是两个对象是否具有相同引用)
**1.2)看个荔枝:**
![这里写图片描述](http://img.blog.csdn.net/20151029191356042)
**Hint)**

  • H1)为了防备name 或 hireDay 可能为null的情况: 需要使用 Objects.equals 方法;如果两个参数都为 null, Objects.equals(a, b) 返回 true; 如果其中一个为null, 则返回 false; 否则,两个参数都不为null, 则调用 a.equals(b);(注意是Objects not Object)
  • H2)利用这个方法, Employee.equals 方法的最后一条语句要改写为:
return Objects.equals(name, other.name)
&& salary == other.salary
&& Objects.equals(hireDay, other.hireDay);

1.3)在子类中定义 equals 方法时, 首先调用超类的 equals; 如果检测失败,对象就不可能相等, 如果超类中的域都相等, 就需要比较子类中的实例域;



1.4)java语言规范要求 equals 具有以下特性:

  • 自反性:非空引用 x,x.equals(x) 应该返回true;
  • 对称性:非空引用x 和 y, x.equals(y) 返回ture, 那么 y.equals(x) 也应该返回ture;
  • 传递性:对于 非空引用x 、y 和 z, x.equals(y) 返回ture, 那么 y.equals(z) 也应该返回ture, 则 x.equals(z) 也应该返回 true;
  • 一致性:如果x 和 y 引用的对象没有发生变化, 反复调用 x.equals(y) 应该返回同样的结果;
  • 对于任意非空应用x, x.equals(null) 应该返回false;

1.5)出现的问题+解决方法

  • 当子类和父类对象分别作为equals 的隐式参数,导致不满足对称性的情况: e.equals(m), 这里的e是一个 Employee对象,m是一个 Manager对象,并且两个对象具有相同的属性值;如果在 Employee.equals中用 instanceof 检测,就会返回 true, 然而这意味着反过来调用:

    m.equals(e) 也需要返回true; 对称性不允许这个方法调用返回 false, 或者抛出异常;猛然间,让人感觉到 instanceof 并不是那么完美;
  • 下面从两个截然不同的情况看一下这个问题:
    • 1)如果子类能够拥有自己的相等概念, 则对称性需要将强制采用getClass 进行检测;
    • 2)如果由超类决定相等的概念, 那么就可以使用 instanceof 进行检测, 这样可以在不同子类的对象间进行相等的比较;

【2】下面给出编写一个完美的 equals 方法的建议:

  • 2.1)显式参数命名为 otherObject, 稍后需要将它转换为另一个叫做 other的变量;
  • 2.2)检测this 与 otherObject 是否引用同一个对象:

    if(this == otherObject) return true; 实际上, 这是一种经常采用的形式, 因为计算这个等式要比一个一个地比较类中的域所付出的代价小得多;
  • 2.3)检测otherObject 是否为 null, 如果为 null ,则返回 false, 这项检测很有必要:

    if(otherObject == null) return false;
  • 2.4)比较this 与 otherObject 是否属于同一个类: 如果equals 的语义在每个子类中有所改变,就是用 getClass 进行检测:if(getClass() != otherObject.getClass()) return false;
  • 2.5) 将 otherObject 转换为 相应的类类型变量:

    ClassName other = (ClassName)otherObject;
  • 2.6)现在开始对所有需要比较的域进行比较了:

    使用 == 比较基本类型域, 使用 equals比较对象域, 如果所有的域都匹配返回 true, 否则返回 false;

    return field1 == other.field1 && Objects.equals(field2, other.field2) && ......;

    如果在子类中重新定义 equals, 就要在其中包含 调用 super.equals(other);

Hint)对于数组类型的域, 可以使用静态的Arrays.equals 方法检测相应的 数组元素是否相等;

Alert)看个荔枝(下面是实现 equals 方法的一种常见的错误):



代码分析(Analysis):

  • A1)这个方法声明的显式参数类型是 Employee, 其结果并没有 覆盖 Object类的 equals 方法,而是定义了一个完全无关的方法;
  • A2)为了避免发生类型错误, 可以使用 @Override 对覆盖超类的方法进行标记;
@Override
public boolean equals(Object other)
  • A3)如果出现了错误,并且正在定义一个新方法,编译器就会给出 错误报告;如, 假设将下面的声明添加到 Employee类中, 就会看到一个错误报告, 这是因为这个方法并没有覆盖超类Object 中的 任何方法:
@Override
public boolean equals(Employee other)

【3】hashCode 方法

3.1)定义:散列码是由对象导出的一个整型值, 散列码没有规律的;如,x和y 是两个不同的对象, x.hashCode() 和 y.hashCode() 基本上不会相同的;

3.2)String 类的 hashCode 散列码:

  • 3.2.1)String类通过下列算法计算散列码:
int hash = 0;
for(int i=0;i<length(); i++)
hash = 31 * hash + charAt(i);
  • 3.2.2) hashCode方法定义在了 Object类, 因此每个对象都有一个默认的散列码, 其值为对象的存储地址:



    对以上打印结果的分析(Analysis):

    • A1)字符串s 和 t 拥有相同的散列码, 这是因为字符串的散列码是由内容导出的, 而字符串缓冲sb 和 tb 却有着不同的散列码,这是因为 在StringBuffer 类中没有定义hashCode 方法,它的散列码是有 Object类的默认 hashCode 方法,以便用户可以 将对象插入到散列表中;
    • A2) hashCode方法应该返回一个整型数值,并合理的组合实例域的散列码, 以便能够让各个不同的对象产生的散列码更加均匀;

3.3)看个荔枝, 下面是 Employee类 的 hashCode方法:



3.4)还可以在java7中做两个改进(improvement):

  • I1) 最好使用 null 安全 的方法 Objects.hashCode , 如果参数为null, 这个方法会返回0, 否则返回对参数调用 hashCode的结果;
  • I2)还有一个方法: 需要组合多个散列值, 可以调用 Objects.hash 并提供多个参数,这个方法会对各个参数调用 Objects.hashCode, 并组合这些散列值; 如 Employee.hashCode 的方法可以简写为:
public int hashCode()
{
return Objects.hash(name, salary, hireDay);
}

Attention)

  • A1) equals 方法与 hashCode 的定义必须一致, 如果x.equals(y) 返回 true, 那么 x.hashCode() 就必须与 y.hashCode() 具有相同的值;
  • A2) 如, 如果用定义的Employee.equals 比较雇员的Id, 那么 hashCode就需要散列Id, 而不是 雇员的 姓名或存储地址;

Hint)如果存在数组类型的域, 那么可以使用静态的 Arrays.hashCode 方法计算一个散列码, 这个散列码由数组元素的散列码组成;

java中的 equals + hashCode的更多相关文章

  1. Java中的equals和hashCode方法

    本文转载自:Java中的equals和hashCode方法详解 Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要 ...

  2. Java中==、equals、hashcode的区别与重写equals以及hashcode方法实例(转)

    Java中==.equals.hashcode的区别与重写equals以及hashcode方法实例  原文地址:http://www.cnblogs.com/luankun0214/p/4421770 ...

  3. java集合(3)- Java中的equals和hashCode方法详解

    参考:http://blog.csdn.net/jiangwei0910410003/article/details/22739953 Java中的equals方法和hashCode方法是Object ...

  4. Java中的equals和hashCode方法详解

    Java中的equals和hashCode方法详解  转自 https://www.cnblogs.com/crazylqy/category/655181.html 参考:http://blog.c ...

  5. 转:Java中的equals和hashCode方法详解

    转自:Java中的equals和hashCode方法详解 Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要重写这 ...

  6. 一文搞懂--Java中重写equals方法为什么要重写hashcode方法?

    Java中重写equals方法为什么要重写hashcode方法? 直接看下面的例子: 首先我们只重写equals()方法 public class Test { public static void ...

  7. Java 中的 equals() 和 hashCode()

    equals() 和 hashCode() 在 Object 类中以本地方法的形式存在,Java 中所有的类都继承了 Object 类,因此所有的类中都包含了这两个方法.这两个方法在 Java 开发中 ...

  8. Java中的equals()和hashCode() - 超详细篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的equals()和hashCode() - 详细篇>,希望对大家有帮助,谢谢 文章纯属原创,个人总结难免有差错,如果有,麻烦在评论 ...

  9. 关于Java中的equals方法

    关于Java中的equals方法 欢迎转载,但是请填写本人的博客园原址https://www.cnblogs.com/JNovice/p/9347099.html 一.什么是equals方法 equa ...

随机推荐

  1. [LeetCode] Sudoku Solver 解数独,递归,回溯

    Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...

  2. Codeforces Round #442 Div.2 A B C D E

    A. Alex and broken contest 题意 判断一个字符串内出现五个给定的子串多少次. Code #include <bits/stdc++.h> char s[110]; ...

  3. Atcoder CODE FESTIVAL 2017 qual C C - Inserting 'x' 回文串

    题目链接 题意 给定字符串\(s\),可以在其中任意位置插入字符\(x\). 问能否得到一个回文串,若能,需插入多少个\(x\). 思路 首先统计出现次数为奇数的字符\(cnt\). \(cnt\ge ...

  4. 《手把手教你学C语言》学习笔记(9)--- 程序的选择控制

    C语言是面向过程编程语言的主要代表,其特征就是严格控制程序的执行语句顺序,因此,C程序的主要结构控制就是顺序控制,以main函数为入口函数,根据控制,一条一条地执行语句.由于实际需求是很复杂的,只用顺 ...

  5. 九、 Java程序初始化的顺序(二)

    之前的一篇博客里我写了关于在一个类中的程序初始化顺序,但是在Java的面向对象里,类之间还存在着继承的关系.所以关于程序的初始化顺序,我们可以再细划分为:父类静态变量,父类的静态代码块,父类构造器,父 ...

  6. [SaltStack] Minion-conf自动更新

    minion-conf配置文件自动更新, 加载 minion-conf是每个minion自身以来的配置, 为了方便我们在中心管控机上(Master)统一配置, 然后下发文件, 进而使得Minion能够 ...

  7. WKWebView携带不上cookie的问题处理

    自从WKWebView推出后Apple官方及众多开发者都推荐使用它代替UIWebView,确实通过加载速度.占用内存方面的对比都要好上几个档次,索性就把项目中的浏览器控件换成了WKWebView,一开 ...

  8. CS Academy Round #65 Count Arrays (DP)

    题目链接  Count Arrays 题意  给定$n$和$m$个区间.若一个长度为$n$的$01$序列满足对于每一个给定的区间中至少有一个位置是$0$, 那么这个$01$序列满足条件.求有多少满足条 ...

  9. POJ3086 Treats for the Cows(区间DP)

    题目链接  Treats for the Cows 直接区间DP就好了,用记忆化搜索是很方便的. #include <cstdio> #include <cstring> #i ...

  10. 洛谷——P1617 爱与愁的一千个伤心的理由

    P1617 爱与愁的一千个伤心的理由 题目背景 (本道题目隐藏了两首歌名,找找看哪~~~) <爱与愁的故事第一弹·heartache>第二章. 经历了心痛后,爱与愁大神不行了. 题目描述 ...