不一样时重写equals和hashCode又怎样

阅读原文:不一样时重写equals和hashCode又怎样!java

可能一问到equals和hashCode相关的问题,就会有人讲他们的自反性,对称性,一致性,传递性等几条约定了, 此时我不得不佩服,这么多约定居然都能记得,但我不知道你是否是真的理解呢。算法

我不一样时重写又能如何呢?

我只能说只要你不碰到这几个主,你也没什么事的!微信

  • 为何不能遇到它们几个呢?ide

    由于它们几个会用到hashCode方法。this

  • 他们用hashCode方法来干吗?spa

    hashCode方法是根据对象的地址生成的一个int整数,默认它和地址一一对应的,若是不重写,那么只有对象地址同样的状况下,哈希值才相等。code

    equals默认用来比较地址是否相同,但当集合中元素增多时,再使用equals判断,效率是比较低的;而哈希值是能够快速定位到指定的元素的, 因此默认Java就使用哈希值来比较定位,所以有了Object.hashCode的约定。orm

    Set怎么实现存储不重复的元素的?HashMap怎么判断相同的key的?有兴趣可去深刻了解一下。cdn

例子

小王在「堆」中有两套房产,这两套房产位于不一样的地址。如今我想要判断这两套房子是不是同一个主人?对象

因而我去问Object,而Object告诉我这两套房产不是一我的的!

我:为何呢?

Object: equals告诉我两套房子离了十万八千里,在不一样的地方(地址),固然不是同一我的了。

我:这逻辑……(不符合咱们常规的认知啊)

既然这样,那我只能重写equals了!

//注意:这是伪代码,省略了不少
//重写equals,认为身份证相同就是同一我的
@Override
public boolean equals(Object obj) {
   return this.idCard == obj.idCard;
}
复制代码

哈哈,好啦,如今equals终于知道这两个房子是同一人的啦!

然而在房产管理局(HashMap)我获得一个消息:小王只要一套房产!

WTF!我白干了!

房产管理局(HashMap): 不信你看!

HashMap<Object, Integer> roomManager = new HashMap<>();

    public void count(){
        User u1 = new User("小王", "34128");
        countRoom(u1);
        User u2 = new User("小王", "34128");
        countRoom(u2);
    }
    public void countRoom(User user){
        boolean exist = roomManager.containsKey(user);
        if (exist) {
            Integer num = roomManager.get(user);
            roomManager.put(user, num++);
        }else {
            roomManager.put(user, 1);
        }
    }
复制代码

遇到你真是倒霉了,原来房产管理局(HashMap)使用了hashCode来计算的!想要正确的统计小王的房产只能重写hashCode方法了。

@Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (idCard != null ? idCard.hashCode() : 0);
        return result;
    }
复制代码

此时,他们统计终于对了!!!

总结

除非你能保证你重写equals的类不被Set,Map使用,不然你就必须同时重写equals和hashCode。

你能保证吗?若是不想同时重写,你能够这样:

/** * 1.此类应用于Set,Map时,须要使用者重写hashCode,违规者后果自负 * 2.本类不能做为第三方类库供其余项目使用 * @author flyhero * @date 2019-04-03 6:14 PM */
public class User {}
复制代码

信不信这样写,老大看到后,就say goodbye了!

如何重写equals与hashCode

我就不写出常说的那些约定性质了,写了也记不住。说说如何避免违反这些约定:

重写equals

  1. 经过==判断是不是同一个引用
  2. 经过instanceof判断是不是相同类型
  3. 把参数转为正确的类型
  4. 对比双方各个属性值是否相同

如:

@Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof User)) {
            return false;
        }
        User user = (User) obj;
        return this.name.equals(user.name)
                && this.idCard.equals(user.idCard);
    }
复制代码

重写hashCode

hashCode方法应该为“不相等的对象产生不相等的哈希值”

通常计算是根据你equals中用来比较的属性的hashCode组合计算的,不过目前JDK和一些类库已经给我提供了很好的重写方式,咱们可没必要去深究其中算法。

  • 方式一

    @Override
    public int hashCode() {
        return Objects.hash(name, idCard);
    }
    复制代码

    使用了JDK自带Objects提供的静态方法。

  • 方式二

    @EqualsAndHashCode
    public class User {}
    复制代码

    使用了lombok类库,直接在类上注解便可。

更多精彩技术文章尽在微信公众号:码上实战

相关文章
相关标签/搜索