本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2024-11(1)

面试题--hashCode与equals

发布于2021-05-29 22:11     阅读(1082)     评论(0)     点赞(0)     收藏(3)


hashCode介绍

hashCode()的作用是获取哈希码,也被称为是散列码,实际是返回一个int整数,这个哈希码的作用是确定该对象在哈希表中的索引位置hashCode()定义在JDK的Object.java中,Java中的任何类都包含有hashCode()函数。散列表存储的是键值对,他的特点是:能根据键快速的检索出对应的值,这其中就利用了散列码。可以快速的找到所需要的对象。
为什么要有hashCode
HashSet如何检查重复为例来说明为什么要有hashCode:

对象加入HashSet时,HashSet会先计算对象的hashCode值来判断对象加入的位置,看该位置是否有值,如果没有,HashSet会假设对象没有重复出现;如果发现有值,这时会调用equals()方法来检查两个对象是否真的相同,如果两者相同,HashSet就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置,这样就大大减少了equals的次数,相应就大大提高了执行速度。

  • 如果两个对象相等,则hashcode一定也是相同的
  • 两个对象相等,对两个对象分别调用equals方法都返回true
  • 两个对象有相同的hashcode值,他们不一定是相等的
  • equals方法被覆盖过,则hashcode方法也必须被覆盖
  • hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode()方法,则该class的两个对象无论如何都不会相等(即使两个对象指向相同的数据)
    为什么重写了equals()方法还需要重写hashCode()方法?
    equals()只判断对象属性是否相同,hashCode()要判断两者的地址是否相同。java中如果要判断两个对象是否相等,需要同时满足地址+属性都相同才可以。
  • 只重写equals()方法,不重写hashCode()方法:
public class Student {
	private String name;
	private int age;
 
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) 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;
	}
	// 省略 get,set方法...
}

如果只重写了equals()方法,而不重写hashCode()方法,可能就会出现两个没有关系的对象equals相同(因为他是根据对象的特征进行重写的),但是hashCode不相同的情况。因为此时 Student 类的 hashcode() 方法就是 Object 默认的 hashcode()方 法,由于默认的 hashcode()方法是根据对象的内存地址经哈希算法得来的,所以 stu1 != stu2,故两者的 hashcode 值不一定相等。
根据 hashcode 的规则,两个对象相等其 hash 值一定要相等,矛盾就这样产生了。上面我们已经解释了为什么要使用 hashcode 算法,所以即使字面量相等,但是产生两个不同的 hashCode 值显然不是我们想要的结果。

  • 重写 equals() 时,也重写了 hashCode() 方法:
public class Student {
	private String name;
	private int age;
	
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@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;
		Student other = (Student) 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;
	}
	// 省略 get,set方法...
}

从 Student 类重写后的 hashcode() 方法中可以看出,重写后返回的新的 hash 值与 Student 的两个属性是有关,这样就确保了对象和对象地址之间的关联性。



所属网站分类: 技术文章 > 博客

作者:黑暗之神

链接:http://www.javaheidong.com/blog/article/207546/aa5271efcce96f91fb25/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

0 0
收藏该文
已收藏

评论内容:(最多支持255个字符)