Java集合框架 Set接口实现类--HashSet存储结构 & HashSet拓展
Posted Z && Y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java集合框架 Set接口实现类--HashSet存储结构 & HashSet拓展相关的知识,希望对你有一定的参考价值。
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);
//1.添加元素
hashSet.add(p1);
hashSet.add(p2);
hashSet.add(p3);
//重复,添加失败
hashSet.add(p3);
//直接new一个相同属性的对象,依然会被添加,不难理解。
//假如相同属性便认为是同一个对象,怎么修改?
hashSet.add(new Person("小明", 21)); // 添加成功
System.out.println(hashSet.toString());
//如何删除new出来的对象?
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) {
//1.是否为同一对象
if (this == obj) {
return true;
}
//2.判断是否为空
if (obj == null) {
return false;
}
//3.判断是否是Student类型
if (obj instanceof Person) {
Person person = (Person) obj;
//4.比较属性
return this.name.equals(person.name) && this.age == person.age;
}
//不满足,返回false
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乘以一个数可以转换成位运算。
以上是关于Java集合框架 Set接口实现类--HashSet存储结构 & HashSet拓展的主要内容,如果未能解决你的问题,请参考以下文章
Java集合框架 Set接口实现类--TreeSet概述及使用