hashCode()和equals()的覆写问题

本文详细解析了在使用HashMap等集合框架时,hashCode()与equals()方法的作用与顺序,通过实验展示了它们如何影响数据的存储与检索,并说明了如何利用这些方法在集合中去重和通过匿名对象获取对应value。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HashMap中的覆写为例,个人总结了一下hashCode()equals()在程序运行中的作用和顺序的问题。

import java.util.Map ;
import java.util.HashMap ;
class Person{
	private String name ;
	private int age ;
	public Person(String name,int age){
		this.name = name ;
		this.age = age ;
	}
	public String toString(){
		return "姓名:" + this.name + ";年龄:" + this.age ;
	}
	public boolean equals(Object obj){            //覆写equals()方法
		System.out.println("E");                      //通过输出"E"与否判断是否调用equals()方法
		if(this==obj){                                            //传入本类对象,返回true,表示是同一对象
			return true ;                       
		}
		if(!(obj instanceof Person)){          //传入非本类对象,返回false,表示不是同一对象
			return false ;
		}
		Person p = (Person)obj ;                       //对象向下转型
		if(this.name.equals(p.name)&&this.age==p.age){          //各属性依次比较,相等返回true,不等返回false
			return true ;
		}else{
			return false ;
		}
	}
	public int hashCode(){                                      //覆写hashCode()方法
		System.out.println("H");                       //通过输出"H"与否判断是否调用hashCode()方法
		return this.name.hashCode() * this.age ; //返回int值得计算公式,可以理解为对象hash值所对应的唯一存储地址
		
	}
};
public class HashMapDemo{
	public static void main(String args[]){
		Map<Person,String> map = null ;
		map = new HashMap<Person,String>() ;
		map.put(new Person("张三",30),"zhangsan1");	// 增加内容
		map.put(new Person("张三",30),"Zhangsan2");	
		map.put(new Person("李四",30),"lisi");	
		System.out.println(map.get(new Person("张三",30))) ;//查找内容
		System.out.println(map.get(new Person("李四",30))) ;
	}
};

程序运行结果:

H

H

E

H

H

E

Zhangsan2

H

E

lisi

将主程序中的代码适当删除,显示不同的运行结果,可以看出hashCode()equals()究竟是怎么被调用的:

实验一:

map.put(new Person("张三",30),"zhangsan1");	// 增加内容
/*map.put(new Person("张三",30),"Zhangsan2");	
map.put(new Person("李四",30),"lisi");	// */
System.out.println(map.get(new Person("张三",30))) ; //查找内容
/*System.out.println(map.get(new Person("李四",30))) ;*/

运行结果:

H

H

E

zhangsan1

结果分析:map.put()中创建了一个Person的匿名对象,然后在内部调用了hashCode()方法,得到它的hash值,没有与之冲突的hash值,则把对象属性放置在它的hash值对应的空间,map.get()则是通过键值来查找value,传入的键值是Person的匿名对象,需要得到它的地址才能返回对应的value值,这时匿名对象在内部调用hashCode()方法,得到一样的hash值,再由equals向下转型后判断出是同一个对象,然后也就由map.get()得到了对应的value值。

实验二:

map = new HashMap<Person,String>() ;
map.put(new Person("张三",30),"zhangsan1");	// 增加内容
map.put(new Person("张三",30),"Zhangsan2");	
/*map.put(new Person("李四",30),"lisi");	// */
System.out.println(map.get(new Person("张三",30))) ; //查找内容
/*System.out.println(map.get(new Person("李四",30))) ;*/

运行结果:

H

H

E

H

E

Zhangsan2

结果分析:第一个"H"出现的原因与实验一中相同,然后第二次向map中增加内容,map.put()中再创建了一个Person的匿名对象,然后在内部调用了hashCode()方法,得到它的hash值,发现有与之冲突的hash值,即hash值相同,此时需要equals()方法来区分是否是同一个对象,对比发现是同一个对象,那么对于map.put()来说,即传入了相同的键值,由于HashMap操作时key值是不能重复的,如果重复则肯定会覆盖之前的内容,所以Zhangsan2覆写Zhangsan1存入它的hash值对应的空间,map.get()方法的运行过程如实验一分析,由于在第二次增加内容时value值被覆盖,所以显示的值变为Zhangsan2.

由上述两次实验也就可以的出源代码中的程序运行结果,第三次内容的增加和查找与实验一相同。

 

当用到集合框架的 Hashtable、HashMap、HashSet的时候,集合若要添加新的元素,先调用这个元素的hashCode()方法,定位到它应该放置的存储位置上。如果这个位置上没有元素,它就可以直接存储在 这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals()方法与新元素进行比较,相同的话就覆盖之前存入的内容,不相同就散列其它的地址。所以由于覆写hashCode()与equals()的作用结果,我们可以去掉集合中的相同元素,也可以通过匿名对象找到相应的value。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值