Java重写对象的equals、toString、hashcode

需求

添加一组商品到目标列表:进入待选择商品列表,已添加的商品显示选中状态,可以取消选中和选中,最后添加所有选中商品到目标列表。

方案

目标列表在一个页面,待选商品列表在一个页面,如何判定待选择商品列表中的商品对象为选中商品。接口Collection中有一个方法contains,在子类List中做了实现来判定某对象是否在列表中。

public boolean contains(Object o) {
        return indexOf(o) >= 0;
}
public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
}

可以看到indexOf中有调用equals方法,默认的继承自Object中的equals方法:

public boolean equals(Object obj) {
        return (this == obj);
}

很多情况在业务系统中判断对象是否相等并不是严格意义上的对象相等,需要我们根据业务重写equals方法,这时候我们在equals中往往需要比较对象中各个值是否相等,于是就重写了equals和toString方法。

  • 重写equals方法就必须重写hashcode方法,为什么要重写hashcode方法呢?
    我们来看一下Object.hashCode的通用约定(摘自《Effective Java》第45页)
  1. 在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,那么,对该对象调用hashCode方法多次,它必须始终如一地返回 同一个整数。在同一个应用程序的多次执行过程中,这个整数可以不同,即这个应用程序这次执行返回的整数与下一次执行返回的整数可以不一致。
  2. 如果两个对象根据equals(Object)方法是相等的,那么调用这两个对象中任一个对象的hashCode方法必须产生同样的整数结果。
  3. 如果两个对象根据equals(Object)方法是不相等的,那么调用这两个对象中任一个对象的hashCode方法,不要求必须产生不同的整数结果。然而,程序员应该意识到这样的事实,对于不相等的对象产生截然不同的整数结果,有可能提高散列表(hash table)的性能。

我们在实际应用过程中,如果仅仅重写了equals(),而没有重写hashCode()方法,会出现什么情况?

字段属性值完全相同的两个对象因为hashCode不同,所以在hashmap中的table数组的下标不同,从而这两个对象就会同时存在于集合中,所以重写equals()就一定要重写hashCode()方法。

对于“为什么重写equals()就一定要重写hashCode()方法?”这个问题应该是有个前提:

就是你需要用到HashMap,HashSet等Java集合。用不到哈希表的话,其实仅仅重写equals()方法也可以吧。而工作中的场景是常常用到Java集合,所以Java官方建议 重写equals()就一定要重写hashCode()方法。

最后附上一个重写这几个方法的类(Android环境下的)

public class HomeGoodsBean{

    public String goods_id;
    public String goods_commonid;
    public String store_id;
    public String store_name;
    public String goods_name;
    public String goods_price;

    @Override
    public String toString() {
        return "HomeGoodsBean{" +
                "goods_id='" + goods_id + '\'' +
                ", goods_commonid='" + goods_commonid + '\'' +
                ", store_id='" + store_id + '\'' +
                ", store_name='" + store_name + '\'' +
                ", goods_name='" + goods_name + '\'' +
                ", goods_price='" + goods_price + '\'' +
                '}';
    }

    @Override
    public int hashCode() {
        return Objects.hash(goods_id, goods_commonid, store_id, store_name, goods_name,goods_price);
    }

    @Override
    public boolean equals(@Nullable Object o) {
        if (this == o){
            return true;
        } else if (! (o instanceof HomeGoodsBean)) {
            return false;
        }
        return this.toString().equals(o.toString());
    }
}

相关文章:
重写equals就必须重写hashCode的原理分析
java重写hashcode方法那点事

推荐阅读更多精彩内容