equals()方法和hashCode()方法

equals()和hashCode()都是Object类中的方法,而Object类又作为Java中的顶级父类,这使绝大多数的类也都继承到了这两个方法

equals方法用于比较两个对象是否相同,Object类中equals方法的实现是比较引用地址来判断的对象是否是同一个对象,通过覆盖该方法可以实现自定义的判断规则;

object的eqauls()方法:

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

hashCode是jdk根据对象的地址或者字符串或者数字计算该对象的哈希码值的方法。

当然我们也可以重写这两个方法

String中的equals()方法:

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        return (anObject instanceof String aString)
                && (!COMPACT_STRINGS || this.coder == aString.coder)
                && StringLatin1.equals(value, aString.value);
    }

Stringequals()方法比较的是字符串的内容

为什么重写equals()

1.Object类中equals方法比较的是两个对象的引用地址,只有对象的引用地址指向同一个地址时,才认为这两个地址是相等的,否则这两个对象就不想等。
2.如果有两个对象,他们的属性是相同的,但是地址不同,这样使用equals()比较得出的结果是不相等的,而我们需要的是这两个对象相等,因此默认的equals()方法是不符合我们的要求的,这个时候我们就需要对equals()方法进行重写以满足我们的预期结果。
3.在java的集合框架中需要用到equals()方法进行查找对象,如果集合中存放的是自定义类型,并且没有重写equals()方法,则会调用Object父类中的equals()方法按照地址比较,往往会出现错误的结果,此时我们应该根据业务需求重写equals()方法。

String中的hashCode()方法:

 public int hashCode() {
        // The hash or hashIsZero fields are subject to a benign data race,
        // making it crucial to ensure that any observable result of the
        // calculation in this method stays correct under any possible read of
        // these fields. Necessary restrictions to allow this to be correct
        // without explicit memory fences or similar concurrency primitives is
        // that we can ever only write to one of these two fields for a given
        // String instance, and that the computation is idempotent and derived
        // from immutable state
        int h = hash;
        if (h == 0 && !hashIsZero) {
            h = isLatin1() ? StringLatin1.hashCode(value)
                           : StringUTF16.hashCode(value);
            if (h == 0) {
                hashIsZero = true;
            } else {
                hash = h;
            }
        }
        return h;
    }

String的hashCode()方法根据字符串的内容生成一个hash值

为什么要重写hashCode()

1.hashCode()方法用于散列数据的快速存储,HashSet/HashMap/Hashtable类存储数据时都是根据存储对象的hashcode值来进行分类存储的,一般先根据hashcode值在集合中进行分类,在根据equals()方法判断对象是否相同。
2.HashMap对象是根据其Key的hashCode来获取对应的Value。
3.生成一个好的hashCode值能提高HashSet查找的性能,差的hashCode值不但不能提高性能,甚至可能造成错误。比如hashCode方法中返回常量,会让,HashSet的查找效率退化为List集合的查找效率;hashCode方法中返回随机数,会让查找结果变的不可预测。
4.好的hashCode生成方式是让对象中的关键属性与质数相乘,并将积相加获取。
 

介绍完了equals()和hashCode(),4,就来说说为什么要同时重写它们两个

hashset和hashmap的底层是通过数组+链表来存储的

 存储一个元素时先调用它的hashCode()得到一个hash值,再通过这个hash确定一个nade[]数组的一个索引,然后调用equals()和该索引处链表中的元素比较如果都不同,再添加到链表上。

以String为例

如果我们只重写hashCode()

String str1="hello";String str2="hello"

str1.hashCode()和str2.hashCode()虽然是相同的,但之后str1.equals(str2)的结果却是false,因为不重写equals(),str1.equals()调用的是object的equals()方法,比较的是str1和str2的地址,这时集合中可能就会出现两个内容为hello的字符串元素。

如果我们只重写equals()

String str1="hello";String str2="hello"

str1.equals(str2)虽然为true,但str1.hashCode()和str2.hashCode()有可能是不相同的(当地址计算出的hash发生hash冲突是,即使地址不同通过地址得到的hash值可能相同),这时集合中也可能会出现两个内容为hello的字符串元素。

所以在使用集合存储我们自定义引用类型时,我们必须同时重写这两个方法

  • 37
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值