结论:
1、重写equals()是为了实现自己的区分逻辑。
2、重写hashCode()是为了提高hash tables的使用效率。
举例:
1、String重写Object的equals方法
2、HashSet是如何保证存储的元素不同的?
首先明白这两个方法是什么来的?
equals()和hashCode()是Object的两个方法。作用有两个:
1、区分两个Object
2、给子类重写,让子类去实现自己的区分逻辑。
看下Object的源码是如何区分两个Object的。
public boolean equals(Object obj) {
return (this == obj);
}
可以看出除了==this,否则两个对象不相同。
对于hashCode,源码注释中这样解释的:
1、它是一个代表Object的整数int值,它有利于哈希表的存储使用。(重要)
2、无论何时调用同一对象此方法,返回值都应是相同的。(equals用到的比较信息没有被修改的情况下)
3、如果equals()方法确定了两个对象相等,则这两个对象的hashCode必须返回相同的值(这点就可以决定重写equals()方法就必须重写hashCode方法了)
4、如果equals()方法确定了两个对象不相等,这个两个对象的hashCode还是有可能相等的。但是我们强烈建议不同的对象应该有着不同的hashCode,这样可以提高hash tables的使用效率。
综上,为什么要重写equals()和hashCode()方法的原因有两个:
1、重写equals()是为了实现自己的区分逻辑。
2、重写hashCode()是为了提高hash tables的使用效率。
下面是举例:重写的重要性
例子1:String重写Object的equals方法,源码如下:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = count;
if (n == anotherString.count) {
int i = 0;
while (n-- != 0) {
if (charAt(i) != anotherString.charAt(i))
return false;
i++;
}
return true;
}
}
return false;
}
public int hashCode() {
int h = hash;
if (h == 0 && count > 0) {
for (int i = 0; i < count; i++) {
h = 31 * h + charAt(i);
}
hash = h;
}
return h;
}
可以看出在重写equals()和hashCode()方法时,字符串中的每一个字符都用上了。这样,"abc"和"adcd"的hashCode肯定不相同。"abc".equals("abc")返回true是我们要的结果,符合我们区分逻辑。而不是像Object的equals方法那样“this == obj”引用相等才相同。所以String需要重写Object的equals方法。
例子2:HashSet是如何保证存储的元素不同的?
看下add方法,源码如下:
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
可以看出,HashSet底层是依靠HashMap实现的,而我们知道,HashMap的键值是不可以重复的(可以为null)。重点来了,HashMap保证键值不重复就是依靠对象的equals()和hashCode()方法。
看HashMap的put方法部分伪代码:
1、key是新加入的对象
2、hash是key的哈希值
3、e是哈希表中的每一个元素
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
1、新值覆盖旧值(这个都是同一个Object PRESENT = new Object();)
2、返回旧值
}
否则新增新的结点存储新值。
可以看出,在HashMap新增key-value的时候,如果hashCode和equals都相同,HashMap不会新增新的结点存储新值。而是在原来的key上覆盖掉value值。那么对于HashSet来说,也就是没有新增元素,因为HashSet的元素来源于HashMap的key集合。
也就是说HashSet保证存储的元素的不同,是通过equals()和hashCode()方法来保证的。这就是为什么我们要重写equals()和hashCode()方法的重要原因之一。
补充:对于equals不相同而hashCode相同的元素集合,在哈希表中会以链表或者红黑树的形式储存!
---------------------
【转载,仅作分享,侵删】
作者:river66
原文:https://blog.csdn.net/river66/article/details/87803663
版权声明:本文为博主原创文章,转载请附上博文链接!
|
|