前言
JDK8之前,底层采用“数组+链表”实现哈希表。而在JDK8之后,底层做了优化。
由于HashSet实质是使用Set接口的类,因此需要遵循Set接口的特征:
Set集合特点:
(1)不可以拥有重复元素
(2)没有带索引方法,不能使用普通for循环遍历(即可以使用增强for遍历)
哈希表数据结构大致如下图:
为了学习和测试哈希表,本文使用自制的学生Student类,存入HashSet中,再遍历其中的元素。通过在Student类中覆写hashCode和equals方法,让哈希表中不存在重复的元素。
搭建最基本的学生类Student
变量为private修饰的name和age,设置set、get和show三种方法。
public class Student {
private String name;
private int age;
public Student(int age,String name)
{
this.age = age;
this.name = name;
}
public void SetName(String name) { this.name = name; }
public void SetAge(int age) { this.age = age; }
public String GetName() { return this.name; }
public int GetAge() { return this.age; }
public void ShowName() { System.out.println(this.name); }
public void ShowAge() { System.out.println(this.age); }
}
重写hashCode和equals方法
本文作者使用vscode书写java代码,对于hashCode和equals方法的重写,可以自动生成,方法是:
【鼠标右键】→【源代码操作】→【Generate …】
在Student类中重写:
//下面是为了哈希表中元素不重复,对hashcode和equals方法进行了自动重写。
@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;
}
测试类
import java.util.HashSet;
public class StudentHashSetDemo {
public static void main(String[] args)
{
//创建HashSet集合对象,集合内存放Student的实例
HashSet<Student> hs = new HashSet<Student>();
//创建学生Student实例对象
Student stu_1 = new Student(20,"小明");
Student stu_2 = new Student(19,"小王");
Student stu_3 = new Student(21,"小李");
Student stu_4 = new Student(21,"小李");
//stu_4为重复对象,用于测试Student类中覆写HashCode()和equals()方法后,哈希表的不重复性
//将学生实例存入哈希表
hs.add(stu_1);
hs.add(stu_2);
hs.add(stu_3);
hs.add(stu_4);
//增强for遍历哈希表
for(Student stu : hs)
{
System.out.println("学生姓名:"+stu.GetName()+" 学生年龄:"+stu.GetAge());
}
}
}