前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >重写equals和hashCode方法

重写equals和hashCode方法

作者头像
晚上没宵夜
发布2020-03-11 17:52:33
8640
发布2020-03-11 17:52:33
举报

1. 来源

Object类中定义了equalhashCode方法,又因为Object是基类,所以继承了Object的类都有这两个方法

先来看看Object类中的equal方法

代码语言:javascript
复制
* @param   obj   the reference object with which to compare.
* @return  {@code true} if this object is the same as the obj
*          argument; {@code false} otherwise.
* @see     #hashCode()
* @see     java.util.HashMap
*/
public boolean equals(Object obj) {
    return (this == obj);
}

从中可以看出,Object类中的equal方法是用 ==来比较的,即二者地址是否相同,这样比较即判断二者是否同一对象

2. 需求

如果比较对象的内部是否相等,而不是比较是否同一对象,该怎么办?有没有想法?其实我们日常也经常使用这种比较,只是没有注意到而已,没错那就是字符串,String.equals( ),虽然不是同一对象,但只要内容相同,就返回true,即:"123".equals("123") == true,那么来看看String内部是如何实现这种功能的

String内部的equals方法

代码语言:javascript
复制
public boolean equals(Object anObject) {
    if (this == anObject) {     // 首先比较地址,如果地址相同,那肯定是同一对象同内容
        return true;
    }
    if (anObject instanceof String) {   // 再判断类型,只有类型相同才能比较内部的值
        String anotherString = (String)anObject;    // 向下转型
        int n = value.length;
        if (n == anotherString.value.length) {  // 比较二者字符串长度,长度不同,内容肯定不同
            char v1[] = value;      // 这里也可以看出字符串底层是数组实现
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {      // 逐一比较二者底层数组的每一个字符
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

3. 重写equals方法

自定义的类该怎么实现equal方法呢?这里得遵循如下规则

  • 两对象若equals相同,则hashCode方法返回值也得相同
  • 两个对象的hashCode返回值相同二者equals不一定相同

从该规则可以知道,重写equals必须重写hashCode方法,因为hashCode是对堆内存的对象产生的特殊值,如果没有重写,不同对象产生的哈希值基本是不同的(哈希碰撞),集合中判断对象是否相同也是先判断哈希值再判断equals,Object的hashCode是native方法,所以不放出源码了,下面直接挂出重写equal的代码(仿照String)

重写自定义类的equals方法

代码语言:javascript
复制
public class User {
    
    private String name;

    public User(String name) {
        super();
        this.name = name;
    }
    
    // 重写equal方法
    @Override
    public boolean equals(Object obj) {
        if(this == obj){
            return true;
        }
        if(obj == null || obj.getClass() != this.getClass()){
            return false;
        }
        User user = (User)obj;
        return this.name.equals(user.name);
    }
    
    // 重写hashCode方法
    @Override
    public int hashCode(){
        return this.name.hashCode();
    }
    
    public static void main(String[] args) {
        
        User user1 = new User("Howl");
        User user2 = new User("Howl");
        
        System.out.println(user1.equals(user2));
    }
}
代码语言:javascript
复制
true

4. 验证集合是否先判断hashCode

当然要使用唯一的集合,这里举例hashSet,还是使用上面的代码

代码语言:javascript
复制
public static void main(String[] args) {
        
    User user1 = new User("Howl");
    User user2 = new User("Howl");

    HashSet<User> hashSet = new HashSet<User>();

    hashSet.add(user1);
    hashSet.add(user2);

    Iterator iterator = hashSet.iterator();
    while(iterator.hasNext()){
        System.out.println(iterator.next());
    }

    System.out.println(user1.hashCode());
    System.out.println(user2.hashCode());
}
代码语言:javascript
复制
User [name=Howl]
2255420
2255420

发现集合只有一个对象,即判断user1,user2为同一对象了

举个反例,即注释掉User类重写的hashCode,再重新运行上面的代码,输出如下

代码语言:javascript
复制
User [name=Howl]
User [name=Howl]
366712642
1829164700

这样就可以验证集合确实是对hashCode来判断二者是否相等的,所以这里得十分十分十分注意,以后使用集合存储对象,如果要判断是否相等,考虑重写equal和hashCode方法

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-02-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 来源
  • 2. 需求
  • 3. 重写equals方法
  • 4. 验证集合是否先判断hashCode
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档