美文网首页
equals()和hashCode()方法

equals()和hashCode()方法

作者: gczxbb | 来源:发表于2019-03-06 22:56 被阅读0次

    一、String类equals()方法

    Object类,equals()方法,默认两个对象==,即内存地址相同,即对象相等。

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

    两个内存地址不同的对象比较时,肯定结果不同,为实现对象在某些情况下比较时相等,子类重写equals()方法,如String类,两个String对象每个字符相同时,自定义equal()相等。

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = length();
            if (n == anotherString.length()) {
                int i = 0;
                while (n-- != 0) {
                    if (charAt(i) != anotherString.charAt(i))
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
    

    String类equals()方法,如果==相等,指向同一内存,一定相等。类型不同时,一定不相等,比较每一个字符相同,认为两个字符串String对象相等。

    二、自定义

    自定义一个User类。

    private String id;
    private String name;
    private String city;
    
    public User(String id, String name, String city) {
        super();
        this.id = id;
        this.name = name;
        this.city = city;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }
    

    三个参数,id,name和city,重写equals()方法,定义id相等时,两个User对象相等,比较id的equals()方法。
    针对自定义设计实体类重写,比较类中特定元素定义对象相等。

    重写String类equal()方法,两个String对象,字符串相同,认为它们相等,但是,在HashSet集合类判断对象相等时,依然会保存两个相同字符的String对象,说明HaseSet认为两个相同字符的String对象不是相等对象。
    HashSet集合类相等对象仅存储一份。

    用User类的例子说明,仅重写equals()方法。

    User user1=new User("1","ch","shanghai");
    User user2=new User("1","ch2","beijing");
    System.out.println(user2==user1);//false,内存不同
    System.out.println(user2.equals(user1));//true,定义id相同的User对象相等
    
    HashSet<User> hashSet=new HashSet();
    hashSet.add(user1);
    hashSet.add(user2);
    System.out.println(hashSet.size());
    

    HashSet集合类认为两个User是不同对象。
    HashSet类,hashCode值相同且equals()相等,才是相等对象。在User类,仅重写equal()方法,未重写hashCode()方法,两个对象hash值按基类Object方法计算。

    Object基类hashCode()方法,根据内存地址的hash算法计算,两个地址不同的对象hashCode值不同,因此,若HashSet类认定是相同对象,需重写hashCode方法。

    三、String类hashCode()方法

    public int hashCode() {
        int h = hash;
        final int len = length();
        if (h == 0 && len > 0) {
            for (int i = 0; i < len; i++) {
                h = 31 * h + charAt(i);
            }
            hash = h;
        }
        return h;
    }
    

    按照每个字符计算hash值,如果两个字符串相同时,hashCode值相等,重写User类的hashCode()方法。

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }
    

    比较id的hashCode(),如果字符串id是字符相同,那么hashCode()相等,这样,两个User对象的hashCode()相等,equals()相等,HashSet集合类只存储一份。

    User user1=new User("1","ch","shanghai");
    User user2=new User("1","ch2","beijing");
    HashSet<User> hashSet=new HashSet();
    hashSet.add(user1);
    hashSet.add(user2);
    HashMap<User,String>hashMap=new HashMap();
    hashMap.put(user1, "str1");
    hashMap.put(user2,"str2");
    System.out.println(user1);
    System.out.println(user2);
    System.out.println(user2==user1);
    System.out.println(user1.hashCode());
    System.out.println(user2.hashCode());
    System.out.println(user2.equals(user1));
    System.out.println(hashSet.size());
    System.out.println(hashMap.size());
    

    打印值

    User [id=1, name=ch, city=shanghai]
    User [id=1, name=ch2, city=beijing]
    false
    80
    80
    true
    1
    1
    

    HashMap类,先hashCode()方法,遍历key的hashCode是否相同,hashCode()相等时,落到同一个bucket中。
    再比较equals()方法,相等,说明key已存,直接更新。如果不重写hashCode()方法,永远不会保存到数组的同一个bucket中。

    四、总结

    两个对象==相等,同一个内存地址,hashCode()方法相等,equals()方法相等。

    两个对象hashCode()方法相等,equals()方法不一定相同,参考HashMap类hashcode冲突处理。

    两个对象equals()方法相等,如果未重写hashCode()方法,hashCode()不会相等,根据基类Object按照内存地址hash,HashSet类集合类会出现问题。


    任重而道远

    相关文章

      网友评论

          本文标题:equals()和hashCode()方法

          本文链接:https://www.haomeiwen.com/subject/xisfpqtx.html