通常不重写上述两个方法,一个类大致是这样的
package com.kusch.ares.aatmp;
import java.util.Objects;
public class Goods {
public String id;
public String name;
public String path;
public Integer price;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
@Override
public String toString() {
return "Goods{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", path='" + path + '\'' +
", price=" + price +
'}';
}
}
此时运行下面这段代码:
public static void main(String[] args) {
Goods goods = new Goods();
goods.setId("1");
goods.setName("1");
goods.setPath("1");
goods.setPrice(1);
Goods goods1 = new Goods();
goods1.setId("1");
goods1.setName("1");
goods1.setPath("1");
goods1.setPrice(1);
System.out.println("goods.equals(goods1):" + goods.equals(goods1));
System.out.println("goods.hashCode() == goods1.hashCode():" + (goods.hashCode() == goods1.hashCode()));
Set<Goods> set = new HashSet<>();
set.add(goods);
set.add(goods1);
System.out.println("输出set元素");
set.forEach(System.out::println);
}
输出结果如下:
goods.equals(goods1):false
goods.hashCode() == goods1.hashCode():false
输出set元素
Goods{id='1', name='1', path='1', price=1}
Goods{id='1', name='1', path='1', price=1}
Process finished with exit code 0
可见,我们给一个对象设置的每个属性都相同,期望就是 这两个对象是一样的 ,
但是此时的结果并不尽人意,那么此时要想实现需求,就需要去重写 equals() 方法,
我们在上述类中添加下面这段代码,重写其 equal() 方法。
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Goods goods = (Goods) o;
return Objects.equals(id, goods.id)
&& Objects.equals(name, goods.name)
&& Objects.equals(path, goods.path)
&& Objects.equals(price, goods.price);
}
代码还是比较简单的,我们判断这两个对象是否一样,那就是要去判断他们的每个值是不是一样的。(此时没有重写hashCode()方法)
接下来在此运行上述main方法可得到如下结果:
goods.equals(goods1):true
goods.hashCode() == goods1.hashCode():false
输出set元素
Goods{id='1', name='1', path='1', price=1}
Goods{id='1', name='1', path='1', price=1}
Process finished with exit code 0
此时可以看到,equals() 比较返回true了,这已经达到了我们的预期结果了,好像不重写 hashCode() 也没什么关系,确实,如果你的对象仅仅是
这么使用的,不需要像main方法中后半段一样放进集合进行操作,那重不重写 hashCode() 对你来说问题不大。但是一旦需要放进集合了,用set举例子,
main方法中,把两个认为一样的对象放进set中,输出时,却输出了两个,说明set集合并不认为它们是一样的对象,那为什么呢?
下面找一下set集合的add方法看一下:
可见它把我们的对象作为key存入了map中,值 PRESENT 是一个虚拟值,不用管。接着往下走
可见 hash(key) 方法就是将我们的对象进行hash计算,再跟hash()方法
到这里应该就明确了,由于我们没有重写 hashCode() 方法导致 goods.hashCode() == goods1.hashCode() 为false,所以被当成了两个对象。
最后吧重写的 hashCode() 方法补上看看结果:
@Override
public int hashCode() {
return Objects.hash(id, name, path, price);
}
运行结果:
goods.equals(goods1):true
goods.hashCode() == goods1.hashCode():true
输出set元素
Goods{id='1', name='1', path='1', price=1}
Process finished with exit code 0
可见一切都符合预期了。
如果你不确定对象的使用场景,那重写equals()必须重写hashCode()方法!