最后
由于篇幅原因,就不多做展示了
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 对象锁和类锁有什么区别?
最后
金三银四到了,送上一个小福利!
【025期】谈谈 Java 中 synchronized 对象锁和类锁有什么区别?]( )
最后
金三银四到了,送上一个小福利!
[外链图片转存中…(img-Ou1RSurf-1715475185006)]
[外链图片转存中…(img-IiCp5of6-1715475185007)]
[外链图片转存中…(img-DbeVhaaX-1715475185007)]