3. 你重写过hashcode和equals么,要注意什么?

SUN官方的文档中规定"如果重定义equals方法,就必须重定义hashCode方法,以便用户可以将对象插入到散列(哈希)表中" 

那么 SUN 公司是出于什么考虑做了这个规定呢? 

在集合框架中的HashSetHashTableHashMap都使用哈希表的形式存储数据,而hashCode计算出来的哈希码便是它们的身份证。哈希码的存在便可以: 

  1. 快速定位对象,提高哈希表集合的性能。
  2. 只有当哈希表中对象的索引即hashCode和对象的属性即equals同时相等时,才能够判断两个对象相等。
  3. 从上面可以看出,哈希码主要是为哈希表服务的,其实如果不需要使用哈希表,也可以不重写hashCode。但是SUN公司应该是出于对程序扩展性的考虑(万一以后需要将对象放入哈希表集合中),才会规定重写equals的同时需要重写hashCode,以避免后续开发不必要的麻烦。
  4. hashCode方法可以这样理解:它返回的就是根据对象的内存地址换算出的一个值。这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。

重写equals时需要注意满足java语言规范对于equals的要求:

Java语言规范要求equals需要具有如下的特性: 

  1. 自反性:对于任何非空引用 x,x.equals() 应该返回 true
  2. 对称性:对于任何引用 x 和 y,当且仅当 y.equals(x) 返回 truex.equals(y) 也应该返回 true
  3. 传递性:对于任何引用 x、y 和 z,如果 x.equals(y)返回 truey.equals(z) 也应返回同样的结果。
  4. 一致性:如果 x 和 y 引用的对象没有发生变化,反复调用 x.equals(y) 应该返回同样的结果。
  5. 对于任意非空引用 x,x.equals(null) 应该返回 false

重写equals时,用eclipes生成的源码:

@Override
public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result + age;
	result = prime * result + ((name == null) ? 0 : name.hashCode());
	return result;
}
@Override
public boolean equals(Object obj) {
	if (this == obj)
		return true;
	if (obj == null)
		return false;
	if (getClass() != obj.getClass())
		return false;
	Dog other = (Dog) obj;
	if (age != other.age)
		return false;
	if (name == null) {
		if (other.name != null)
			return false;
	} else if (!name.equals(other.name))
		return false;
	return true;
}
注意: 1.equalshashCode的定义必须一致,两个对象 equalstrue,就必须有相同的 hashCode。反之,如果两个对象的hashcode相同,equals不一定相同。 2.当重写equals方法时,一定要同时把hashcode方法一并重写,因为要保证在实现hash表的扩展性


你可能感兴趣的:(java基础)