==
- 基本数据类型:比较的是他们的值。
- 引用数据类型:比较的就是地址值是否相同
equals
public boolean equals(Object obj) {
return (this == obj);
}
Object类中定义了一个equals的方法,通过源码我们可以看到,其实它本质上还是==,通常我们需要重写equals(),使它比较对象内容是否相等。例如:String、Integer、Date等类就重写了equals()。
hashCode
- hashCode() 的作用是获取哈希码,也称为散列码
- 同一个对象调用超过一次时,hashCode方法必须返回相同的哈希值,前提是不修改在对象的对等比较中使用的信息。
- 不同的对象调用hashCode方法必须产生不同的哈希值。
- 哈希码的作用是确定该对象在哈希表中的索引位置。
hashCode() 和 equals() 有什么关系?
在不会创建“类对应的散列表的情况下”
该类的“hashCode() 和 equals() ”没有半毛钱关系!
equals() 用来比较该类的两个对象是否相等,而hashCode() 则根本没有任何作用。
会创建“类对应的散列表的情况下”
会创建类对应的散列表”是指:在 HashSet, HashTable, HashMap等这些本质是散列表的数据结构中,用到该类。
该类的“hashCode() 和 equals() ”是有关系的:
- 如果两个对象相等,那么它们的hashCode()值一定相同。
- 如果两个对象hashCode()相等,它们并不一定相等。因为在散列表中,hashCode()相等,即两个键值对的哈希值相等。然而哈希值相等,并不一定能得出键值对相等,此时就出现所谓的哈希冲突场景。
在该情况下,为什么重写了equals()一定要重写hashCode() 。
- 重写了equals()使拥有相同内容的不同对象,判断为同一个对象。
- 没有重写hashCode(),它认为拥有相同内容的对象是不同的对象,返回不同的哈希值。这就出现了同一个对象调用hashCode()返回不同的哈希值。
- 而HashSet, HashTable, HashMap等是先通过hashCode方法判断,哈希值不同认为是不同的对象,哈希值相同再调用equals()判断对象是否是同一个对象。
- 这就有可能在HashSet, HashTable, HashMap等 中有重复元素出现。其根本原因是:equals认为拥有相同内容的对象是同一个对象,而hashCode认为拥有相同内容的对象不是同一个对象。
- 所以我们还需要重写hashCode(),使hashCode()判断拥有相同内容的对象为同一个对象。
举例:下⾯的代码中,新建了两个等价的对象,并将它们添加到 HashSet 中。我们希望将这两个对象当成⼀样 的,只在集合中添加⼀个对象。但是 EqualExample 没有实现 hashCode() ⽅法,因此这两个对象的哈希值是不同的,最终导致集合添加了两个等价的对象。
EqualExample e1 = new EqualExample(1, 1, 1);
EqualExample e2 = new EqualExample(1, 1, 1);
System.out.println(e1.equals(e2)); // true
HashSet<EqualExample> set = new HashSet<>();
set.add(e1);
set.add(e2);
System.out.println(set.size()); // 2