zoukankan      html  css  js  c++  java
  • 为什么重写了equals方法一般也要重写hashCode方法

    现在假设我们有一个矩形类Rectangle 

    public class Rectangle {
    private int length;
    private int width;

    public Rectangle(int length, int width) {
    this.length = length;
    this.width = width;
    }
    }
    先回顾下我们为什么要覆盖equals方法呢?现在我们有两个矩形类的对象实例rectangle1 和rectangle2。

    Rectangle rectangle1 = new Rectangle(3, 4);
    Rectangle rectangle2 = new Rectangle(4, 3);
    我想知道两个矩形是否是相等的,如果使用==运算符的话,比较的是rectangle1的引用和rectangle2的引用分别指向的对象在堆中存储的位置。两个对象是先后new出来的,所以肯定是在堆中有两个不同的对象,得到的结果就必然是false。

    System.out.println(rectangle1 == rectangle2);
    输出结果:false
    这并不是我们想要的,我们的目的并不是想知道这两个引用是否是指向同一个对象,而是想知道这两个矩形的长宽是否相同,简单来说我们想要的是通过逻辑判断来得知这两个矩形rectangle1和rectangle2是否相等。所以我们通过覆盖equals方法来实现。

    @Override
    public boolean equals(Object obj) {
    Rectangle o = (Rectangle) obj;
    if (length == o.length){
    if (width == o.width){
    return true;
    }else return false;
    } else if (width == o.length) {
    if (length == o.width) {
    return true;
    }else return false;
    }
    return false;
    }
    这个equals方法中,我们制定的规则是两个矩形,有相同的长、宽,即认为两个矩形是相同的。

    这时再通过equals方法来判断两个矩形是否相等

    System.out.println(rectangle1.equals(rectangle2));
    输出结果: true

    到这里我们已经满足了我们判断两个矩形是否相同的需求了。

    那我们为什么还要覆盖hashCode方法呢?

    如果这个矩形类是需要放进类似HashMap之类的基于哈希表来实现的容器中并作为key时,就有必要覆盖hashCode方法,按照我们自定的规则来得到一个矩形对象的hash值。(如果不指定,默认一般是通过将该对象的内部地址转换成一个整数来实现的)

    HashMap<Rectangle, String> map2 = new HashMap<>(16);
    map2.put(rectangle1, "nice");
    map2.put(rectangle2, "bad");
    System.out.println("size:"+map2.size());
    输出结果:size:2

    我们已经认为rectangle1和rectangle2在逻辑上是相同的了,也就是rectangle1和rectangle2是同一个key了,在put方法添加rectangle2的时候,“bad”理应覆盖掉“nice”,size应该为1,但事实却并发我们想的这样,哈希表在计算数组下标的时候,是会调用此对象的hashCode方法,如果我们没有覆盖hashCode方法,计算hash值时则会将该对象的堆地址转换成一个整数hash值,这在很大概率上是会将rectangle1和rectangle2分配在两个不同的散列桶中。

    想要让rectangle1和rectangle2做为同一个key,在散列时落在同一个桶中,我们就必须要来覆盖hashCode方法

    @Override
    public int hashCode() {
    //以下的17、31都是任意指定大小的数字。
    int result = 17;
    //这里我简单指定面积相同的矩形,hashCode值就相同
    result = 31 * result + length*width;
    return result;
    }
    这时再试一次

    HashMap<Rectangle, String> map2 = new HashMap<>(16);
    map2.put(rectangle1, "nice");
    map2.put(rectangle2, "nice");
    System.out.println("size:"+map2.size());
    输出结果:size:1

    这下得到了我们想要的结果。

    我们在覆盖了hashCode方法之后,要问问自己”我们认为逻辑相等的实例是否都具有相等的散列码”。通过编写单元测试来验证一下你的推断。

    总结:需要做逻辑相等判断的类,覆盖equals方法,如果还需要在散列表(HashMap、HashSet)中作为key,需要覆盖hashcode方法。


    转自
    原文:https://blog.csdn.net/gkmmg/article/details/80296238

  • 相关阅读:
    img与特殊布局下对浏览器渲染的剖析
    css属性image-redering详解
    nodejs与Promise的思想碰撞
    跨域抓取博客园RSS
    WebGL中图片多级处理(FrameBuffer)
    WebGL中的OpenGL着色器语言
    三角剖分算法(delaunay)
    用原生Canvas写贪吃蛇及问题解决
    那些在BAE上部署node.js碰到的坑
    js实现jquery的offset()
  • 原文地址:https://www.cnblogs.com/xp0813/p/11293996.html
Copyright © 2011-2022 走看看