美文网首页
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