一、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; } }