我们经常在面经中看到这样的问题,为什么重写equals方法就一定要重写hashcode方法。本文就是分析这个问题。

<!--more-->

在阿里巴巴java开发手册中就给出了这样的规则。

【强制】关于 hashCode 和 equals 的处理,遵循如下规则: 1) 只要重写 equals,就必须重写 hashCode。 2) 因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的对象必须重写这两个方法。 3) 如果自定义对象做为 Map 的键,那么必须重写 hashCode 和 equals。 说明:String 重写了 hashCode 和 equals 方法,所以我们可以非常愉快地使用 String 对象作为 key 来使用。

看下面的代码,有什么问题吗?

import java.util.HashMap;
import java.util.Map;

public class Five {
   
public static class Person{
String name;
int age; public Person(String name, int age) {
this.name = name;
this.age = age;
}
} public static void main(String[] args) {
       
        Map<Person, Integer> map = new HashMap<>();
        map.put(new Person("sisi", 18), 9);
        map.put(new Person("lili", 12), 2);
        map.put(new Person("lili", 12), 1);
         
         
        System.out.println(map.toString());
        System.out.println(map.get(new Person("sisi", 18)));
        System.out.println(map.get(new Person("lili", 12)));
         
}
}

运行后的结果为:

{com.chr.binarysearch.Five$Person@7852e922=1, com.chr.binarysearch.Five$Person@15db9742=9, com.chr.binarysearch.Five$Person@6d06d69c=2}
null
null

我们不难看出new Person("lili", 12)这个对象作为key,竟然加入到HashMap中两次,违背了HashMap中key是唯一的原则。我们可以插入System.out.println(new Person("lili", 12).hashcode());来获得两次添加到HashMap中对象的hashcode的值。

2018699554
118352462

虽然对象相同,但是hashcode值不同,这也解释了通过对象获取value值为null。

那么该如何保证自定义类对象作为key的唯一性?

重写equals方法和hashcode方法。

在java核心技术 卷1中给出了编写一个完美的equals方法的建议:

public boolean equals(Object otherObj){
  1)检测this与otherObj是否引用同一个对象:
  if(this == otherObj){
    return true;
  }
  2)检测otherObj是否为null,如果为null,返回false。
  if(otherObj == null){
  return false;
  }
  3)比较this与otherObj是否属于同一个类。
  if(getClass() != otherObj.getClass()){
  return false;
  }
  4)将otherObj转换成相应的类型变量:
  ClassName other = (ClassName)otherObj;
  5)开始对所有需要比较的域进行比较。使用==比较基本类型域,使用equals比较对象域。
  return field1 == other.field1
      && Objects.equals(field2, other.field2);
}

这是我自己重写的equals方法

public boolean equals(Object otherObj) {
if(this == otherObj) {
return true;
}
          if(otherObj == null) {
          return false;
          }
           
          if(!(otherObj instanceof Person)) {
          return false;
          }
           
          Person other = (Person)otherObj;
return Objects.equals(name, other.name) && age == other.age;
}
}

之所以用objects.equals(name,other.name);防止空指针异常。

重写hashcode方法

public int hashCode() {
return Objects.hash(name,age);
}

equals与hashcode分析的更多相关文章

  1. == 和 equals,equals 与 hashcode,HashSet 和 HashMap,HashMap 和 Hashtable

    一:== 和 equals == 比较引用的地址equals 比较引用的内容 (Object 类本身除外) String obj1 = new String("xyz"); Str ...

  2. java中的==、equals()、hashCode()源码分析(转载)

    在java编程或者面试中经常会遇到 == .equals()的比较.自己看了看源码,结合实际的编程总结一下. 1. ==  java中的==是比较两个对象在JVM中的地址.比较好理解.看下面的代码: ...

  3. java中的==、equals()、hashCode()源码分析

    转载自:http://www.cnblogs.com/xudong-bupt/p/3960177.html 在Java编程或者面试中经常会遇到 == .equals()的比较.自己看了看源码,结合实际 ...

  4. Java String引起的常量池、String类型传参、“==”、“equals”、“hashCode”问题 细节分析

    在学习javase的过程中,总是会遇到关于String的各种细节问题,而这些问题往往会出现在Java攻城狮面试中,今天想写一篇随笔,简单记录下我的一些想法.话不多说,直接进入正题. 1.String常 ...

  5. ArrayList_HashSet的比较及Hashcode分析

    ArrayList_HashSet的比较及Hashcode分析 hashCode()方法的作用   public static void main(String[] args) { Collectio ...

  6. Java中的equals和hashCode方法

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

  7. Java提高篇——equals()与hashCode()方法详解

    java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...

  8. Java实战equals()与hashCode()

    一.equals()方法详解 equals()方法在object类中定义如下: 代码 public boolean equals(Object obj) { return (this == obj); ...

  9. 关于equals和hashCode

    equals()和hashCode()是Object类的两个函数,重要性可见一斑,不过我们平时使用却未必能深入理解他们.本文从java doc触发,讲到它们与哈希表的关系,再到具体的实现,就我目前掌握 ...

随机推荐

  1. 机器学习算法中的网格搜索GridSearch实现(以k-近邻算法参数寻最优为例)

    机器学习算法参数的网格搜索实现: //2019.08.031.scikitlearn库中调用网格搜索的方法为:Grid search,它的搜索方式比较统一简单,其对于算法批判的标准比较复杂,是一种复合 ...

  2. Jquery元素筛选、html()和text()和val三者区别

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. java 饮料换购

    饮料换购 乐羊羊饮料厂正在举办一次促销优惠活动.乐羊羊C型饮料,凭3个瓶盖可以再换一瓶C型饮料,并且可以一直循环下去,但不允许赊账. 请你计算一下,如果小明不浪费瓶盖,尽量地参加活动,那么,对于他初始 ...

  4. Spark Deploy 模块

    Spark Scheduler 模块的文章中,介绍到 Spark 将底层的资源管理和上层的任务调度分离开来,一般而言,底层的资源管理会使用第三方的平台,如 YARN 和 Mesos.为了方便用户测试和 ...

  5. eshop2-linux 软件源配置 and 建议

    1. 阿里云源配置:http://mirrors.aliyun.com/ 2. 源配置 2.1 sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.r ...

  6. python矩阵运算大全(linalg模块)

    python矩阵的运算大全 python矩阵运算可以用numpy模块,也可以用scipy模块,主要运算包括以下几种: #1-1python矩阵运算所需模块 import numpy as npimpo ...

  7. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-stop

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  8. .NET via C#笔记12——泛型

    12 泛型 使用值类型作为参数的泛型容器,传入值类型的参数时,不需要进行装箱 12.1 FCL中的泛型 System.Array中提供了很多泛型方法 AsReadOnly BinarySearch C ...

  9. 剑指offer系列(六)

    题目描述: 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList,例如按照链表顺序,1->2->3->4->5->6->7->8,那么我们将得到{8 ...

  10. POJ 2155:Matrix 二维树状数组

    Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 21757   Accepted: 8141 Descripti ...