散列集合类存入对象的时候必须重写equal和hashCode方法
看hashmap和hashtable中的putVal方法中都有
//hashmap中
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
//hashtable中
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
意思是如果这个对象的的hash和key相同就覆盖原来的值(hashmap多了直接对key进行判断地址),如果不重写hashcode方法就是这个对象的地址进行计算得到散列码
执行以下代码:
public static void main(String[] args) {
User User1 = new User("用户1", 21);
User User2 = new User("用户1", 22);
User User3 = new User("用户1", 21);
HashSet<User> set = new HashSet<>();
set.add(User1);
set.add(User2);
set.add(User3);
System.out.println(User1.hashCode());
System.out.println(User2.hashCode());
System.out.println(User3.hashCode());
set.forEach(x -> System.out.println(x.name + " " + x.age));
}
正常来说,应该只有两个对象,就是有因为我们没有重写equal和hashcode方法,导致集合认为这是三个不同的对象,他们的hashcode也个不相同
现在我们重写hashcode和equal方法
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
User user = (User) o;
return Objects.equals(name, user.name) &&
Objects.equals(age, user.age);
}
再次执行:
、
@EqualsAndHashCode
这个也会去重写equal和hashcode方法,而且判断条件也更加严格
public int hashCode() {
int PRIME = true;
int result = 1;
Object $age = this.age;
int result = result * 59 + ($age == null ? 43 : $age.hashCode());
Object $name = this.name;
result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
public boolean equals(final Object o) {
if (o == this) {
return true;
} else if (!(o instanceof User)) {
return false;
} else {
User other = (User)o;
if (!other.canEqual(this)) {
return false;
} else {
Object this$age = this.age;
Object other$age = other.age;
if (this$age == null) {
if (other$age != null) {
return false;
}
} else if (!this$age.equals(other$age)) {
return false;
}
Object this$name = this.name;
Object other$name = other.name;
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$name.equals(other$name)) {
return false;
}
return true;
}
}
}