Java-HashSet
类型:类,实现Set接口
特点:
- 不存储重复元素
- 不保证存储的顺序
底层数据结构:哈希表
哈希表:
JDK8之前,底层采用数组+链表实现。
JDK8之后,长度比较长时底层进行了优化。
HashSet存储元素的过程:
使用hashSet存储Student对象:
Student类:
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//重写toStirng、equals和hashCode()方法,IDEA里面打出方法名可以自动生成。
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
测试类:
import java.util.HashSet;
import java.util.Iterator;
public class HashSetMain {
public static void main(String[] args) {
HashSet<Student> hashSet = new HashSet<>();
hashSet.add(new Student("猪小明",30));
hashSet.add(new Student("蘑菇头",27));
hashSet.add(new Student("闰土",35));
hashSet.add(new Student("闰土",35));
Iterator<Student> it = hashSet.iterator();
System.out.println("hashSet集合大小:"+hashSet.size());
System.out.println("遍历:");
while (it.hasNext()) {
Student s = it.next();
System.out.println(s);
}
}
}
运行结果:
hashSet集合大小:3
遍历:
Student{name=‘蘑菇头’, age=27}
Student{name=‘闰土’, age=35}
Student{name=‘猪小明’, age=30}
可以看到,集合大小是3,有两个对象的name和age是相同的,在执行add()方法时,重复的元素不会被添加进去,但这是在Student类重写了equals方法和hashCode方法之后的结果。如果Student类不对equals()和hashCode()进行重写,不管两个Student的name和age内容是否一样,都会被添加到hashSet集合中,至于为什么会这样,可以从hashSet的add()方法的源码一步步向上找,可以找出原因。本人叙述能力有限,这里不作叙述。
可以验证一下,在Student类中将重写的equals()和hashCode()方法注释掉,再执行测试类,查看结果:
hashSet集合大小:4
遍历:
Student{name=‘猪小明’, age=30}
Student{name=‘闰土’, age=35}
Student{name=‘闰土’, age=35}
Student{name=‘蘑菇头’, age=27}
可以看到,集合大小是4,有两个Student对象name和age相同,但都被添加进去了。
由此可见,如果我们想要用HashSet存储对象,最好是重写(覆盖)equals()和hashCode()方法,防止两个属性完全相同的对象都被添加到集合中。