重新认识下hashCode和equals

/ 0评 / 0

前言

关于equals以及hashCode相关知识网上已经非常非常多了,最近在看到这篇博文的时候总感觉还是少了些,故自己写了一些测试代码,然后总结一下到底这两个有什么相同点以及不同点。

equals

equals方法是用来比较两个对象是否相等,一般来说要想编写一个合格的equals方法需要以下几个步骤

1、判断对象内存地址是否相等

2、判断对象class类型是否相等

3、判断字段

class TestPerson {
	public String name;
	public int age;
	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;
		TestPerson that = (TestPerson) o;
		return age == that.age &&
				Objects.equals(name, that.name);
	}
}

equals方法在List、Queue的数据结构中经常用到,比如List#contains、List#indexOf,判断元素是否相等。

hashCode

hashCode方法是用来生成当前对象的哈希码,一般来说,同一个对象的哈希码是一样的,但是相同的哈希码不一定是同一个对象(哈希冲突),既然我们通过equals可以判断是否为统一同一对象,那么为什么还需要hashCode。

对于Set、Map等数据结构来说,判断元素是否重复使用equals的话,那么就每一次都需要遍历所有元素,那么就失去了其原来的目的(空间换时间),所以这时候对于Set、Map则会使用对象的hashCode来计算出对象的存储位置,然后使用equals去判断对象是否相同,如果不同,那么就发生了哈希冲突,至于如何解决哈希冲突,则不是我们的问题了。

下面的例子是使用Objects为我们提供的Hash计算方法。

class TestPerson {
	public String name;

	public int age;

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;
		TestPerson that = (TestPerson) o;
		return age == that.age &&
				Objects.equals(name, that.name);
	}

	@Override
	public int hashCode() {
		return Objects.hash(name, age);
	}
}

总结

equals方法是用来判断两个对象是否相等,默认的实现为直接判断对象内存地址是否相同,我们可以覆写然后判断指定的字段

hashCode方法只是用来获取对象的哈希码,当哈希码不同那么Set、Map则会将其当做两个不一样的对象,所以才必须:同一个对象的hashCode的返回值必须一样。当我们没有覆写hashCode方法,那么会导致Set中可以存在equals相同的元素(因为通过HashCode算出的位置不同,然后就是两个不同的对象了),Map中Key可以为equals相同的元素(原理一样)。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注