Java HashSet类的用法(非常详细)
HashSet 是 Java Set 接口中的一个实现类。HashSet 类存储的元素是不可重复的,并且元素都是无序的。
HashSet 类在存储每个元素时先调用该元素的 hashCode() 方法生成一个唯一的整数标识——散列码(Hashcode),先根据散列码确定元素的存储位置,再调用元素对象的 equals() 方法来确保该位置没有重复元素。HashSet 类之所以能快速实现元素查询也与此有关。
定义 HashSet 类的语法格式如下:
HashSet 类的缺点是保存的元素没有特定顺序。Java 还提供了一种新的 HashSet 类——LinkedHashSet,该类通过一个链表来维护添加的元素的顺序,即遍历顺序和插入顺序是一致的。LinkedHashSet 类的所有方法与 HashSet 类的方法是一致的。
【实例】 HashSet集合的应用。
HashSet 集合之所以能确保不出现重复的元素,是因为先后调用了 hashCode() 方法和 equals() 方法,执行过程是:当调用 HashSet 集合的 add() 方法存入元素时,首先调用当前存入元素的 hashCode() 方法获得对象的哈希值,然后根据对象的哈希值计算出一个存储位置。若该位置上没有元素,则直接将元素存入;若该位置上有元素,则调用 equals() 方法将当前存入的元素依次和该位置上的元素进行比较。如果返回的结果为 false,那么将该元素存入集合中;如果返回的结果为 true,说明有重复元素,那么将该元素舍弃。
当向集合中存入元素时,为了保证 HashSet 正常工作,要求在存入元素时重写 Object 类中的 hashCode() 方法和 equals() 方法。在上面实例中,将字符串存入集合中时,调用的是 String 类重写的 hashCode() 方法和 equals() 方法。但是如果将自定义类型的对象存入集合中,那么必须重写上述两个方法。
【实例】HashSet集合的应用——存入自定义类型的对象。
在上面实例的基础上,下面的实例修改了 Student 类,并且重写 hashCode() 方法和 equals() 方法,条件是 id 相同的学生就是同一个学生。
【实例】HashSet 集合的应用——存入自定义类型的对象,重写 hashCode() 方法和 equals() 方法。
HashSet 类在存储每个元素时先调用该元素的 hashCode() 方法生成一个唯一的整数标识——散列码(Hashcode),先根据散列码确定元素的存储位置,再调用元素对象的 equals() 方法来确保该位置没有重复元素。HashSet 类之所以能快速实现元素查询也与此有关。
定义 HashSet 类的语法格式如下:
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, SerializableHashSet 类的构造方法如下:
- HashSet():构造一个新的空集合,具有默认的初始容量(16)和负载因子(0.75)。
- HashSet(Collection<?extends E>c):构造一个包含指定集合中的元素的新集合。
- HashSet(int initialCapacity):构造一个新的空集合,具有指定的初始容量和默认的负载因子(0.75)。
- HashSet(int initialCapacity,float loadFactor):构造一个新的空集合,具有指定的初始容量和负载因子。
HashSet 类的缺点是保存的元素没有特定顺序。Java 还提供了一种新的 HashSet 类——LinkedHashSet,该类通过一个链表来维护添加的元素的顺序,即遍历顺序和插入顺序是一致的。LinkedHashSet 类的所有方法与 HashSet 类的方法是一致的。
【实例】 HashSet集合的应用。
import java.util.HashSet; public class Demo { public static void main(String[] args) { HashSet nameset = new HashSet<>(); nameset.add("张三"); nameset.add("李四"); // 添加重复元素 nameset.add("张三"); // 输出 HashSet 集合 System.out.println(nameset); } }运行结果如下:
[李四, 张三]
使用 add() 方法在 HashSet 集合中依次添加 3 个字符串元素并输出。由运行结果可知,取出元素的顺序与添加元素的顺序并不一致,并且重复存入的元素“张三”只输出一次。HashSet 集合之所以能确保不出现重复的元素,是因为先后调用了 hashCode() 方法和 equals() 方法,执行过程是:当调用 HashSet 集合的 add() 方法存入元素时,首先调用当前存入元素的 hashCode() 方法获得对象的哈希值,然后根据对象的哈希值计算出一个存储位置。若该位置上没有元素,则直接将元素存入;若该位置上有元素,则调用 equals() 方法将当前存入的元素依次和该位置上的元素进行比较。如果返回的结果为 false,那么将该元素存入集合中;如果返回的结果为 true,说明有重复元素,那么将该元素舍弃。
当向集合中存入元素时,为了保证 HashSet 正常工作,要求在存入元素时重写 Object 类中的 hashCode() 方法和 equals() 方法。在上面实例中,将字符串存入集合中时,调用的是 String 类重写的 hashCode() 方法和 equals() 方法。但是如果将自定义类型的对象存入集合中,那么必须重写上述两个方法。
【实例】HashSet集合的应用——存入自定义类型的对象。
import java.util.HashSet; class Student { String id; String name; public Student(String id, String name) { this.id = id; this.name = name; } public String toString() { return id + ":" + name; } } public class Demo { public static void main(String[] args) { HashSet<Student> nameset = new HashSet<>(); Student student1 = new Student("001", "张三"); Student student2 = new Student("002", "李四"); Student student3 = new Student("001", "张三"); nameset.add(student1); nameset.add(student2); // 添加重复元素 nameset.add(student3); // 输出 HashSet 集合 System.out.println(nameset); } }运行结果如下:
[001:张三, 002:李四, 001:张三]
运行结果中出现了两条相同的学生信息,这样的学生信息被视为重复元素。为什么会出现这种情况呢?这是因为在定义 Student 类时没有重写 hashCode() 方法和 equals() 方法,创建的这两个学生对象 student1 和 student3 所引用的对象地址不同,所以被它们认为是两个不同的对象。在上面实例的基础上,下面的实例修改了 Student 类,并且重写 hashCode() 方法和 equals() 方法,条件是 id 相同的学生就是同一个学生。
【实例】HashSet 集合的应用——存入自定义类型的对象,重写 hashCode() 方法和 equals() 方法。
import java.util.HashSet; class Student { String id; String name; public Student(String id, String name) { this.id = id; this.name = name; } public String toString() { return id + ":" + name; } // 重写hashCode()方法 public int hashCode() { // 返回id属性的哈希值 return id.hashCode(); } // 重写equals()方法 public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof Student)) { return false; } Student student = (Student) obj; boolean boo = this.id.equals(student.id); return boo; } } public class Demo { public static void main(String[] args) { HashSet<Student> nameset = new HashSet<>(); Student student1 = new Student("001", "张三"); Student student2 = new Student("002", "李四"); Student student3 = new Student("001", "张三"); nameset.add(student1); nameset.add(student2); // 添加重复元素 nameset.add(student3); // 输出HashSet集合 System.out.println(nameset); } }运行结果如下:
[001:张三, 002:李四]
由运行结果可知,HashSet 集合认为 student1 和 student3 两个对象相同,因此删除了重复的元素。