Java之hashCode覆写异常(对象做主键,主键的hashCode和变量有关系),在Map中存了元素却查询不到

一、学习记录之hashCode函数覆写,hashCode覆写和变量有关导致修改变量前在Hash集合中存储的元素查找不到。

二、用示例说明查找不到的原因----和Hash结构集合存储元素有关,由于修改前后的hash码不同造成查找不到;谨记在覆写hashCode函数时一定尽可能避免hash值和变量产生关系,否则会有意想不到的异常发生

1、员工类:--在该类中覆写了hashCode函数,并且hashCode值和年龄可修改变量有关系,如下:

@Override
public int hashCode() {
	// TODO Auto-generated method stub
	int employeeHashCode = super.hashCode() + age;
	return employeeHashCode;
}

2、测试说明过程:

     在employPositionMap中存了员工和员工职位映射,初始employeeJack年龄为28保存到employPositionMap中,修改年龄为26,再从employPositionMap集合中查询employeeJack,查询结果为null,但实际在employPositionMap中保存了employeeJack;原因是对象的hash码不一致,查找的位置不一样,用图1说明,可能初始存的位置为2,而查询位置为5,所以查不到想要的,或者即使巧合查到,也不一定是期望的值。具体代码如下:

1234567

                                                                                    图1  存储位置说明

     运行效果如图2所示:由于查找前修改了和hashCode有关的变量,修改前可以查到,修改后查找期望对象失败,为null;如下图所示:

三、异常复现代码如下

1、Empolyee类:

/**
 * 员工类,包含ID,姓名和年龄
 * @author fengbin15
 */
public class Employee {
	//员工ID
	private int id;
	//员工姓名
	private String name;
	//员工年龄
	private int age;
	
	/**
	 * 构造函数
	 * @param id
	 * @param name
	 * @param age
	 */
	public Employee(int id, String name, int age)
	{
		this.id = id;
		this.name = name;
		this.age = age;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		int employeeHashCode = super.hashCode() + age;
		return employeeHashCode;
	}

	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		return super.equals(obj);
	}
}

2、测试主类:

/**
 * 复现hashCode覆写异常
 * @author fengbin15
 */
public class HashCodeTest {
	/**
	 * 测试主函数
	 * @param args
	 */
	public static void main(String[] args)
	{
		//员工职位映射表--------该用法比较特殊,但可能会由于特殊原因用到
		Map<Employee, String> employPositionMap = new HashMap<Employee, String>();
		//添加职员
		Employee employeeMike = new Employee(20200401, "Mike", 25);
		Employee employeeMary = new Employee(20200402, "Mary", 26);
		Employee employeeJack = new Employee(20200403, "Jack", 28);
		Employee employeeTom = new Employee(20200404, "Tom", 23);
		Employee employeeLucy = new Employee(20200405, "Lucy", 21);
		Employee employeeJim = new Employee(20200406, "Jim", 26);
		Employee employeeDavid = new Employee(20200407, "David", 29);
		employPositionMap.put(employeeMike, "Manager");
		employPositionMap.put(employeeMary, "Staff");
		employPositionMap.put(employeeJack, "Staff");
		employPositionMap.put(employeeTom, "Staff");
		employPositionMap.put(employeeLucy, "Staff");
		employPositionMap.put(employeeJim, "Staff");
		employPositionMap.put(employeeDavid, "Staff");
		
		//修改前查找对象,可以查找到,如下:
		String beforeFind = employPositionMap.get(employeeJack);
		System.out.println("修改前查询:" + beforeFind);
		//修改employeeJack职员的年龄------在职员的Employee对象的hashCode与年龄有关
		employeeJack.setAge(26);
		//在员工职位存储列表中查询jack的职位
		String afterFind = employPositionMap.get(employeeJack);
		System.out.println("修改后查询:" + afterFind);
	}
}

以上为自己遇到的问题,记录下来,供参考;如有不合适的地方,欢迎指正,共同进步,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值