Java中hashCode和equals的关系

Java中hashCode和equals的关系


什么是hashCode
hashCode是对象的散列值,也叫哈希值。默认情况下是根据对象的存储地址进行哈希映射得到的一个整数值。散列值可以提高查找的效率,主要应用于散列存储结构中快速确定对象的存储位置,如HashSet、HashMap。

比如HashSet,它的内部采用对某个数字n进行取余的方式对散列值进行分组和划分对象的存储区域。当从HashSet集合中查找某个对象时,先调用对象的hashCode方法获得该对象的散列值,然后根据散列值找到相应的存储区域,最后调用equals,遍历该存储区域内的每个元素与该对象逐一比对,一个优秀的哈希算法能大大减少查找的时间开销。

equals和“==”的区别
JDK中Object类自带的equals方法作用和“==”一致,都是简单的判断两个对象的地址是否相同。但在实现具体的类时,可以覆盖父类的equals方法,来实现自己想要的功能,比如比较两个对象内容是否相等。

hashCode和equals的关系
hashCode方法主要是用于查找,而equals方法主要是用于两个对象的比较。一般来说只有在散列存储结构中才会用到hashCode方法。比如HashSet的contains方法,要判断集合中是否含有某个对象,它会先调用hashCode方法,查找若得到的哈希值相同,才会继续调用equals方法比较这两个对象是否相等。

如果你只覆盖了某个类的equals,那么当你想要使用HashSet时,集合中可能会出现两个内容相同的对象。因此,当你想覆盖euqals方法的时候,也要覆盖hashCode方法,这是一个好习惯。

重写方法时要注意的问题
当我们需要重写这两个方法时,要注意以下三点:
(1)若两个对象equals结果为true,则其hashCode结果应该相同;
(2)两个对象的hashCode相同,不代表两个对象的equals结果为true;
(3)如果你重写了equals,那么你也应该重写hashCode。

另外,JAVA的基本数据类型和String类重写了父类的hashCode和equals。对于基本数据类型,hashCode就是简单的返回数值,equals就是比较数值的大小;对于String类,它通过一种复杂的计算来实现hashCode和equals是等价的,当且仅当两个字符串的内容相同。

重写hashCode带来的问题
我们来看看下面这个例子。我重写了Person类的hashCode方法,将一个Person类的对象加入到HashSet后,修改它fields的取值后,调用contains方法显示该对象并不在集合中。为什么会出现这种情况?原因是显然的,我们修改了name的取值,导致这个对象的散列值发生变化,这时候HashSet再调用hashCode查找时,可能就找不到了。

class Person{
	
	private String name;
	
	public Person(String name) {
		this.name = name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	@Override public int hashCode() {
		int len = name.length(), hashcode=0;
		for(int i=0; i<len; i++) {
			hashcode += name.charAt(i);
		}
		return hashcode;
	}
}
	Set<Person> set = new HashSet<Person>();
	Person p = new Person("hashCode");
	set.add(p);
	p.setName("Change");			
	System.out.println(set.contains(p));//false

因此,如果你的类重写了hashCode方法,且类的字段参与了散列值的计算,那么我们就不应该轻易修改它的字段。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值