ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java常用API(五)—— 重写对象的equals和hashCode方法

2021-05-09 13:31:12  阅读:147  来源: 互联网

标签:Java equals hashCode return Line 重写 public


未重写前,调用父类Object的equals方法,该方法比较的是引用对象存储的值:即对象在堆中的地址。

package com.JavaSe.eq;


class Line{
    double k, b;
    public Line(double kk, double bb){
        this.k = kk;
        this.b = bb;
    }

}
public class TestEq {
    public static void main(String[] args) {
        Line line1 = new Line(1.5, 2.2);
        Line line2 = new Line(1.5, 2.2);
        System.out.println(line1.equals(line2));//false
    }
}

只重写equals不重写hashCode

package com.JavaSe.eq;


import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

class Line{
    double k, b;
    public Line(double kk, double bb){
        this.k = kk;
        this.b = bb;
    }
    //重写equals方法: 比较k和b是否相等
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Line line = (Line) o;
        return Double.compare(line.k, k) == 0 &&
                Double.compare(line.b, b) == 0;
    }



    @Override
    public String toString() {
        return "Line{" +
                "k=" + k +
                ", b=" + b +
                '}';
    }
}
public class TestEq {
    public static void main(String[] args) {
        Line line1 = new Line(1.5, 2.2);
        Line line2 = new Line(1.5, 2.2);
        System.out.println(line1.equals(line2));//重写完之后比较结果为:true

        Set<Line> set = new HashSet<>();
        set.add(line1);
        set.add(line2);
        System.out.println(set); // [Line{k=1.5, b=2.2}, Line{k=1.5, b=2.2}]
        System.out.println( line1.hashCode() == line2.hashCode()); //false

    }
}

可以发现,equals比较的结果为true,我们认定相同{k,b}为同一对象,这符合我们的要求。但是使用HashSet添加上述两个对象的时候,居然都添加进去了。这显然不符合我们的预期。这是因为hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。而上述对象没有重写hasCode方法,两个对象的hashCode值不一样,也就被认定为两个不同的对象了。

通过看 hashSet 的 add 方法能够得知 add 方法里面使用了对象的 hashCode 方法来判断,所以我们需要重写 hashCode 方法来达到我们想要的效果。

重写equals和hashCode

如何计算对象的hashCode

生成一个 int 类型的变量 result,并且初始化一个值,比如17。
对类中每一个重要字段,也就是影响对象的值的字段,也就是 equals 方法里有比较的字段,进行以下操作:
a. 计算这个字段的值 filedHashValue = filed.hashCode();
b. 执行 result = 31 * result + filedHashValue;

package com.JavaSe.eq;


import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

class Line{
    double k, b;
    public Line(double kk, double bb){
        this.k = kk;
        this.b = bb;
    }
    //重写equals方法: 比较k和b是否相等
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Line line = (Line) o;
        return Double.compare(line.k, k) == 0 &&
                Double.compare(line.b, b) == 0;
    }

    //计算HashCode
    @Override
    public int hashCode() {
        return Objects.hash(k, b);
    }

    @Override
    public String toString() {
        return "Line{" +
                "k=" + k +
                ", b=" + b +
                '}';
    }
}
public class TestEq {
    public static void main(String[] args) {
        Line line1 = new Line(1.5, 2.2);
        Line line2 = new Line(1.5, 2.2);
        System.out.println(line1.equals(line2));//重写完之后比较结果为:true
        Set<Line> set = new HashSet<>();
        set.add(line1);
        set.add(line2);
        System.out.println(set); //[Line{k=1.5, b=2.2}]
        System.out.println( line1.hashCode() == line2.hashCode()); //true

    }
}

参照Objects.hash(k, b)的源码,hashCode计算方法也可写成如下:

    @Override
    public int hashCode() {
        //使用包装类
        Double kk = this.k;
        Double bb = this.b;
        int result = 1;
        result = 31 * result + (kk == null ? 0 : kk.hashCode());
        result = 31 * result + (bb == null ? 0 : bb.hashCode());
        return  result;
    }

参考文章:

Java 如何重写对象的 equals 方法和 hashCode 方法

标签:Java,equals,hashCode,return,Line,重写,public
来源: https://blog.csdn.net/weixin_44855907/article/details/116561322

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有