1. HashSet存储结构
注:hashSet存储过程:
- 根据hashCode计算保存的位置,如果位置为空,则直接保存,否则执行第二步。
- 执行equals方法,如果方法返回true,则认为是重复,拒绝存储,否则形成链表。
问题: 如何不让新增new出来的匿名对象 & 如何删除new出来的匿名对象?
首先这里有一个Person类:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试代码:
public static void main(String[] args) {
HashSet<Person> hashSet = new HashSet<>();
Person p1 = new Person("小明", 21);
Person p2 = new Person("小李", 22);
Person p3 = new Person("小周", 21);
hashSet.add(p1);
hashSet.add(p2);
hashSet.add(p3);
hashSet.add(p3);
hashSet.add(new Person("小明", 21));
System.out.println(hashSet.toString());
System.out.println();
hashSet.remove(new Person("小明", 21));
System.out.println(hashSet.toString());
}
假如相同属性便认为是同一个对象,怎么修改? 思路: 要解决该问题问题,可以重写hashCode和equals代码:
现在的Peson类: 重写了hashCode和equals方法
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int hashCode() {
return this.name.hashCode() + age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (obj instanceof Person) {
Person person = (Person) obj;
return this.name.equals(person.name) && this.age == person.age;
}
return false;
}
}
再次运行刚刚的测试代码:
- 可以发现已经解决了不让新增new出来的匿名对象 & 删除new出来的匿名对象的问题
2. HashSet拓展:
IDEA可以自动帮我们重写hashCode和equals方法
-
鼠标右键,选择Generate -
选择equals()和hashCode() 3. 点击next -
选择判断对象相等的依据,然好点击next -
与上一步同理 -
点击Finish
可以发现IDEA帮我们自动生成了2个方法:
运行刚刚的测试代码:
点进去hashCode源码:
发现hashCode方法底层实现为:
hashCode方法里为什么要使用31这个数字大概有两个原因:
- 31是一个质数,这样的数字在计算时可以尽量减少散列冲突。
- 可以提高执行效率,因为31*i=(i<<5)-i,31乘以一个数可以转换成位运算。
|