专栏首页码字搬砖再论:关于 equals 和 hashCode

再论:关于 equals 和 hashCode

上篇 关于 equals 和 hashCode 关于 equals 和 hashCode 的基本性质已经论述过了。

1.什么时候应该覆盖 equals? 我们知道 equals 默认比较的内存地址,即是否为同一个对象。如果类具有了自己特有的逻辑相等,即属性值等,的概念时,并且超类没有覆盖或者覆盖了单不满足子类需求的情况下重写 equals。

但对于类似枚举类这样的 class 而言,每个属性最多只存在一个对象,逻辑相等与内存地址相等时一样的,不需要重写。

2.为什么要覆盖 equals( hashCode) ?

/**
 * @author shengjk1
 * @date 2020/3/14
 */
public class TestEquals {
	public static void main(String[] args) {
		HashMap<Student, String> map = new HashMap<>();
		Student student = new Student(16, "小明");
		map.put(student, "a");
		Student student1 = new Student(16, "小明");
		System.out.println(map.containsKey(student1));
	}
}

class Student {
	private int age;
	private String name;
	
	public Student(int age, String name) {
		this.age = age;
		this.name = name;
	}
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int age) {
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	//	@Override
//	public boolean equals(Object o) {
//		if (this == o) return true;
//		if (o == null || getClass() != o.getClass()) return false;
//		Student student = (Student) o;
//		return age == student.age &&
//				Objects.equals(name, student.name);
//	}
//
	@Override
	public int hashCode() {
		return Objects.hash(age, name);
	}
}

结果

false

这完全不是我们想要的,我们希望的是 map.containsKey(student1) 为true。但为什么是 false 呢?通过源码我们可以知道 应为 equals 不等,导致的。同理,对于 hashCode 也是如此。

3.是否是任何时候都需要覆盖 equals 和hashCode? 答案是 否定的。 还记得上一篇说过的吗,JDK 内部就有违背 equals hashCode 一致性规则的。另外的话,hashCode 仅仅针对 hash 表来说才有用。

/**
 * @author shengjk1
 * @date 2020/3/14
 */
public class TestEquals {
	public static void main(String[] args) {
		HashMap<Student, String> map = new HashMap<>();
		Student student = new Student(16, "小明");
		map.put(student, "a");
		Student student1 = new Student(16, "小明");
		System.out.println("map " + map.containsKey(student1));
		
		ArrayList<Student> students = new ArrayList<>();
		students.add(student);
		System.out.println("list " + students.contains(student1));
	}
}

class Student {
	private int age;
	private String name;
	
	public Student(int age, String name) {
		this.age = age;
		this.name = name;
	}
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int age) {
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;
		Student student = (Student) o;
		return age == student.age &&
				Objects.equals(name, student.name);
	}
//
//	@Override
//	public int hashCode() {
//		return Objects.hash(age, name);
//	}
}

结果

map false
list true

对于 list 而言,根本就不需要 比较hashCode,我们也违背了 equals 与 hashCode 的一致性,但对于 students.contains(student1) 结果就是正确的

4.总结 1.java 集合内部比较对象是否相等一般用的都是 equals ,所以 equals 是要尽量重写的。 2.而对于 hashCode 来说,对于 hash table 来说是必须要重写的,其他的可以不重写。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • java反射的简单使用

    前几天项目中遇到一个相对有意思的事情,那就是一个InsertHbase的工具类接收一个对象,然后获取到对象的每一个属性及其值,最后Insert到Hbase中 ...

    shengjk1
  • 关于Iterator和Iterable

    shengjk1
  • 逆波兰表达式求值

    1.什么是逆波兰表达式? 也叫后缀表达式,(3+4)*5-6 对应的逆波兰表达式 3 4 + 5 * 6 -

    shengjk1
  • JDK1.9-Set接口

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    cwl_java
  • 在Google Cloud platform上的Kubernetes集群部署HANA Express

    在Google Cloud platform的Kubernetes cluster上,新建一个hxe.yaml文件:

    Jerry Wang
  • python---爬取英雄联盟皮肤图片

    爬LOL的皮肤高清图片的大致步骤就是用selenium去爬取英雄联盟所以英雄的皮肤的url地址,然后在用requests库去将图片下载到本地。

    sjw1998
  • yii2 scenarios()如何理解?? [ 2.0 版本 ] 转

    最近在使用场景的时候碰到一些不解的问题,我简单模拟下: 我新建一张表info,有name和age2个字段 模型代码:

    双面人
  • Java 学习笔记(4)——面向对象

    现在一般的语言都支持面向对象,而java更是将其做到很过分的地步,java是强制使用面向对象的写法,简单的写一个Hello Word都必须使用面向对象,这也是当...

    Masimaro
  • springboot (三)JdbcTemplate

    IT故事会
  • python3 __name__

    所以我们平常见到的__name__ == "__main__"就是指当前文件作为脚本运行时会发生的一些事情, 防止当前文件作为模块导入时运行自己不想运行的代码

    py3study

扫码关注云+社区

领取腾讯云代金券