【027期】面试必问 hashCode() 和 equals() 及使用规范,你掌握了吗?

最后

由于篇幅原因,就不多做展示了

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

if(o instanceof Person){

Person p = (Person)o;

return this.age == p.getAge() && this.name.equals(p.getName());

}

return false;

}

}

运行类:

public class Application {

public static void main(String[]args){

Set set = new HashSet<>();

Person p1 = new Person(“Lilei”, 25);

Person p2 = new Person(“Lilei”, 25);

set.add(p1);

System.out.println("p1 equals p2: " + (p1 == p2));//1

System.out.println("set contains p1: " + set.contains(p1));//2

System.out.println("set contains p2: " + set.contains(p2));//3

}

}

输出结果:

p1 equals p2: false

set contains p1: true

set contains p2: false

看出来p1虽然等于p2(我们换了个人类的方法),但是把p1可以动态一套,通过p2之后是无法取出来的,但是我们要的效果是可以通过p2取出来的,实景中肯定是有这样的使用场景的。

因为集存储不是重复的对象,两个哈希码和等于进行判断,所以集存储的对象必须改这方法

还是上面的例子,我们不改写人类的方法,也不改写它的hashCode。

public class Person {

private String name;

private int age;

public Person() {

}

public Person(String name, int age) {

this.name = name;

this.age = age;

}

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;

}

}

运行类:

public class Application {

public static void main(String[]args){

Set set = new HashSet<>();

Person p1 = new Person(“Lilei”, 25);

Person p2 = new Person(“Lilei”, 25);

set.add(p1);

set.add(p2);

System.out.println("set size is: " + set.size());

//System.out.println("p1 equals p2: " + (p1 == p2));

//System.out.println("set contains p1: " + set.contains(p1));

//System.out.println("set contains p2: " + set.contains(p2));

}

}

运行结果:

set size is: 2

设置里面是不重复的,如果不重写Person类的hashCode和等价的方法,这里p1和p2是可以同时动态设置对象里的。那么我们只重写了Person的hashCode方法能不能行呢?

@Override

public int hashCode(){

return name.hashCode() * 31 + age;

}

运行结果:

set size is: 2

最后重写Person类的equals()方法:

@Override

public boolean equals(Object o){

if(this == o){

return true;

}

if(o instanceof Person){

Person p = (Person)o;

return this.age == p.getAge() && this.name.equals(p.getName());

}

return false;

}

@Override

public int hashCode(){

return name.hashCode() * 31 + age;

}

运行结果:

set size is: 1

如果自定义对象做为 Map 的键,那么必须重写 hashCode() 和 equals()

这一点和第二点实际上是一样的,这里就不举例介绍了。

实际上,Set的对象和Map的key的操作和hashCode以及equals方法有关,比如查这个对象是否在Set里,先根据hashCode定位到一个段,在根据equals进行确定是否存在,这样不需要把Set里所有的对象都遍历一遍,效率太低,Map的key是同样道理。

那么hashCode和equals的设计原则就呼之欲出了。

equals()的设计原则

=============

  • 对称性:如果x.equals(y)返回为真,那么y.equals(x)也应该返回为真。

  • 反射性:x.equals(x)必须返回为true。

  • 类推性:如果x.equals(y)返回为true,而且y.equals(z)返回为true,那么z.equals(x)也应该返回为true。

  • 一致性:如果x.equals(y)返回是真的,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是真的。

  • 非空性:x.equals(null),永远返回是false;x.equals(和x不同类型的对象)永远返回是false。

hashCode()的设计原则

===============

  • 在一个 Java 的执行期间,如果对象提供了一个等于做比较的信息,则该对象多次调用hashCode()方法,该方法必须始终如一返回同一个整数。

  • 如果两个对象根据(Object)方法相同,则调用调用插件的hashCode()必须产生同一个整数结果。

  • 不是根据要求equals(java.lang.Object) 不完全相同的两个对象,调用方法公开方法的hashCode()必须生成不同的eger结果。整数结果,有可能会提高哈希表的性能。

作者:飞格士图

github.com/feigeswjtu/java-basics/edit/master/sourceCode

往期精选  点击标题可跳转

【017期】面试官问:Java 中 for、foreach、stream 哪个处理效率更高?

【018期】JDK1.8 中 HashMap 底层实现原理源码分析,你 get 到了吗?

【019期】告诉面试官,我能优化 Group By,而且知道得很深!

【020期】面试官问:Java 遍历 Map 集合有几种方式?效率如何?

【021期】面试官问:Java 中 new 一个对象的过程中发生了什么?这有些夸张了!

【022期】ArrayList 使用 forEach 遍历时删除元素会报错吗?

【023期】Spring 中 @Transactional 是如何实现的?源码解读原理

【024期】说说为什么要拆分数据库?有哪些方法?
【025期】谈谈 Java 中 synchronized 对象锁和类锁有什么区别?

最后

金三银四到了,送上一个小福利!

image.png

image.png

专题+大厂.jpg

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

【025期】谈谈 Java 中 synchronized 对象锁和类锁有什么区别?]( )

最后

金三银四到了,送上一个小福利!

[外链图片转存中…(img-Ou1RSurf-1715475185006)]

[外链图片转存中…(img-IiCp5of6-1715475185007)]

[外链图片转存中…(img-DbeVhaaX-1715475185007)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值