JAVA - 【为什么要重写hashCode和equals?】HashSet
JAVA_VERSION="14"
JAVA_VERSION_DATE="2020-03-17"
引入:
在用户自定义类中,重写equals是为了灵活的比较自定义类,而不是使用继承Object类的equals方法;
为什么不直接使用Object类的equals方法,因为Object类的equals方法底层比较采用的是==,而==针对引用类型比较的是地址值(无意义):
那为什么要重写hashCode方法呢?
1> HashSet使用测试(String类与自定义Student类)
package kyleeo.util01;
import java.util.HashSet;
public class HushMapDemo {
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
set.add("aaaa");
set.add("bbbb");
set.add("aaaa");
set.add("cccc");
for(String i:set) {
System.out.println(i);
}
HashSet<Student> set2 = new HashSet<Student>();
set2.add(new Student("aaa",15));
set2.add(new Student("aaa",14));
set2.add(new Student("aaa",15));
set2.add(new Student("bbb",21));
for(Student i:set2) {
System.out.println(i.getName()+"---"+i.getAge());
}
}
}
结果:
aaaa
bbbb
cccc
aaa---15
aaa---15
bbb---21
aaa---14
为什么HashSet集合中存储自定义类型Student的时候不能做到唯一添加呢?
因为添加使用到add方法,继续查看源码中add方法的实现:
继续进入put:
此处可以看到HashSet在进行添加底层使用到了hash方法,而hash值的获取实际上是在hashCode基础上的一系列操作,
在上述框中:
首先会判断待添加数据hash值与原数据hash值是否一致,String类型因为重写了hashCode所以内容一致的String的hashCode也一致,自定义类型由于没有重写hashCode,用的是从Object继承下来的hashCode,而这个hashCode针对不同对象具有不同值;
所以针对自定义类型,上述框中重复比较第一条一直不通过(为false),与后面条件&&后依旧为false,无法再进行验证!
至此,对于自定义类需要手动实现hashCode,hash值一致后还会调用equals再次进行检测,判断内容是否一致;
为什么还要用equals比较呢?因为hash值毕竟只是一个逻辑值,不同的对象有几率出现相同的hash值。
自定义hashCode和equals之后:
( 可以使用eclipse自动生成该类对应的hashCode方法和equals方法 )
自定义Student类:
package kyleeo.util01;
public class Student {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
附加:
HushSet没有特殊方法,一般使用Collection中的基本方法。
推荐阅读
-
JAVA - 【为什么要重写hashCode和equals?】HashSet
-
HashMap中的key为什么不能为可变对象(除非重写它的hashcode方法和equals方法)
-
HashMap中对象作Key为什么要重写equals和hashcode
-
当集合中的对象要去重时,为什么要重写hashCode和equals方法
-
Java基础---为什么要重写hashCode和equals方法
-
为什么重写 equals() 要重写 hashCode()? hashCode 值相等,两个对象不一定相等?
-
Java 中重写equals()方法时为什么要重写hashCode()方法?
-
java中重写equals和重写hashCode()
-
java中重写equals()方法的同时要重写hashcode()方法(详解)
-
java中重写equals()方法的同时要重写hashcode()方法(详解)