自定义对象重写hashcode方法和equals方法,以及hashSet如何判断重复对象

public class SendDdataVo {

    private int srcSystem = 1;
    private int tarSystem;
    private String srcOrgCode;
    private String tarOrgCode;
 
    public Integer getSrcSystem() {
        return srcSystem;
    }

    public void setSrcSystem(Integer srcSystem) {
        this.srcSystem = srcSystem;
    }

    public Integer getTarSystem() {
        return tarSystem;
    }

    public void setTarSystem(Integer tarSystem) {
        this.tarSystem = tarSystem;
    }

    public String getSrcOrgCode() {
        return srcOrgCode;
    }

    public void setSrcOrgCode(String srcOrgCode) {
        this.srcOrgCode = srcOrgCode;
    }

    public String getTarOrgCode() {
        return tarOrgCode;
    }

    public void setTarOrgCode(String tarOrgCode) {
        this.tarOrgCode = tarOrgCode;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        SendDdataVo other = (SendDdataVo) obj;
        if (srcSystem != other.srcSystem) {
            return false;
        } else if (tarSystem != other.tarSystem) {
            return false;
        } else if (srcOrgCode != other.srcOrgCode) {
            return false;
        } else if (tarOrgCode != other.tarOrgCode) {
            return false;
        }else {
            return true;
        }
    }
    @Override
    public int hashCode() {
        int result  = 17;
        int hashCode = 0;
        int i = srcOrgCode != null ? srcOrgCode.hashCode() : 0;
        int j = tarOrgCode != null ? tarOrgCode.hashCode() : 0;
        hashCode = i + j + srcSystem + tarSystem;
        return result * 31 + hashCode;
    }
}


重写hashcode方法

要重写自己的hashCode方法并没有什么绝对正确的答案,但是我们的目标是:不相等的对象尽可能有不同的hashCode,而且必须满足的一个通用约定是:相等的对象应该具有相同的hashCode。下面介绍的仅仅是一种

  1. 定义一个初始值,一般来说取17。int result = 17;

  2. 分别解析自定义类中与equals方法相关的字段(假如hashCode中考虑的字段在equals方法中没有考虑,则两个equals的对象就很可能具有不同的hashCode)

    情况一:字段a类型为boolean 则[hashCode] = a ? 1 : 0;

    情况二:字段b类型为byte/short/int/char, 则[hashCode] = (int)b;

    情况三:字段c类型为long, 则[hashCode] = (int) (c ^ c>>>32);

    情况四:字段d类型为float, 则[hashCode] = d.hashCode()(内部调用的是Float.hashCode(d), 而该静态方法内部调用的另一个静态方法是Float.floatToIntBits(d))

    情况五:字段e类型为double, 则[hashCode] = e.hashCode()(内部调用的是Double.hashCode(e), 而该静态方法内部调用的另一个静态方法是Double.doubleToLongBits(e),得到一个long类型的值之后,跟情况三进行类似的操作,得到一个int类型的值)

    情况六:引用类型,若为null则hashCode为0,否则递归调用该引用类型的hashCode方法。

    情况七:数组类型。(要获取数组类型的hashCode,可采用如下方法:s[0]*31 ^ (n-1) + s[1] * 31 ^ (n-2) + ..... + s[n-1], 该方法正是String类的hashCode实现所采用的算法)
  1. 对于涉及到的各个字段,采用第二步中的方式,将其依次应用于下式:result = result * 31 + [hashCode];

补充说明一点:如果初始值result不取17而取0的话,则对于hashCode为0的字段来说就没有区分度了,这样更容易产生冲突。比如两个自定义类中,一个类比另一个类多出来一个或者几个字段,其余字段全部一样,分别new出来2个对象,这2个对象共有的字段的值全是一样的,而对于多来的那些字段的值正好都是0,并且在计算hashCode时这些多出来的字段又是最先计算的,这样的话,则这两个对象的hashCode就会产生冲突。hashCode方法的实现没有最好,只有更好。


重写equals方法

equals方法的要求:

  1. 自反性:对于任何非空的两个对象,a.equals(b)都应该返回true

  2. 对称性:对于任何引用a和b,当且仅当a.equals(b)返回true时,b.equals(a)也应该返回true

  3. 传递性:对于任何引用a,b,c,如果a.equals(b)返回true,b.equals©返回true,那么c.equals(a)也应该返回true

  4. 一致性:如果a和b的引用没有发生变化,那么反复调用a.equals(b)的结果应该相同

  5. 对于任何非空的引用a,a.equals(null)应该返回false


hashSet判断重复对象

在java的集合中List 有序,可重复 ,Set 无序,唯一
查看源码得知:
自定义对象重写hashcode方法和equals方法,以及hashSet如何判断重复对象_第1张图片
HashSet集合对象如何判断数据元素是否重复:
检查待存对象hashCode值是否与集合中已有元素对象hashCode值相同,如果hashCode不同则表示不重复, 如果hashCode相同再调用equals方法进一步检查,equals返回真表示重复,否则表示不重复。

如图中所示,在调用以上方法时,在HashSet类中都会执行红框中的代码去判断传入的对象是否和集合中已存在的对象们重复,首先判断对象所对应的hashCode值是否相同,而Java中的hashCode值是由对象的地址所确定的,每一个地址对应一个值

你可能感兴趣的:(java,java基础)