Equals()和HashCode()方法的密切关系

一、equals方法是判断俩个对象是否相等的唯一依据

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

equals方法是Object类定义的方法,在Object中equal方法比较的内存地址,无法判断对象的具体内容是否一样。要对内容准确的判断必须重写equals方法,如java中String、Integer、Double等包装类都做了equals方法的重写。

String类:

    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

Integer:(数字本身就唯一,惊不惊喜)

    public static int hashCode(int value) {
        return value;
    }

二、为什么要用到hashCode方法

我们知道在重写equals方法后,必须重写hashCode方法。

并且要保证:

1、equals方法为true的两个对象,hashCode方法的返回值必须相同。

2、并不要求两个不同对象的hashCode值一定不同。

那么之所以要用到hashCode方法,是为了查询效率。

例如:HashSet这个集合,它的元素,必须是唯一的。要保证它的唯一,用equals是可以实现的,但是如果元素较多,假如有一万个元素,那么就要调用一万次equals方法进行比较,才能确定要不要添加这个元素。同样,查询也一样,要比较一万次,才能确定集合里有没有这个元素。

那么,现在使用HashCode方法,可以形象的理解,每一个元素的hashcode值就是它在集合中的位置。

在插入的时候,因为保证了equeal相同的对象,hashcode值一定相同,所以

1、首先看看该HashCode值对应的集合位置有没有元素存在。

2、如果不存在,说明集合没有该元素,插入;如果存在,在调用equals方法进行比较。值为true,不插入;值为false,插入(怎么插入相同位置?可以在相同HashCode值位置维护一个链表,毕竟不同元素HashCode值可能相同)。

同样,在查询的时候,也是

1、先查询该元素的hashCode

2、再去hashCode值对应的集合位置依次比较链表的各个元素。

这个查询效率是不是显著增加。这其实就是Hash算法,一个叫hash的人首先发现的。

所以在使用一个HashSet存储自定义实体类时,一定要重写Equals和hashCode方法,否则HashSet并不会起到无序的作用。

总结:equals是比较两个对象内容是否相同的唯一依据,hashCode值只是帮助集合快速找到该对象可能存在的位置。

其实,HashSet的实现,是保存在HashMap的key中。

    public HashSet() {
        map = new HashMap<>();
    }

    public Iterator<E> iterator() {
        return map.keySet().iterator();
    }

    public int size() {
        return map.size();
    }

以上的HashSet方法可以明显看书,HashSet其实就是借用了HashMap的Key。

三、一个简单实体类重写Equals和HashCode(IntelliJ自动生成)

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.HashSet;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CustomData {
    private String name;
    private Integer age;


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;

        CustomData that = (CustomData) o;

        if (!name.equals(that.name)) return false;
        return age.equals(that.age);
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + name.hashCode();
        result = 31 * result + age.hashCode();
        return result;
    }
}
就算这个世道烂成一堆粪坑,那也不是你吃屎的理由
原文地址:https://www.cnblogs.com/whalesea/p/12934644.html