数据结构-HashSet

在 Java 编程的世界里,集合框架是极为重要的一部分,而 HashSet 作为 Set 接口的典型实现类,在处理不允许重复元素的场景中频繁亮相。今天,我们就一同深入探究 HashSet,梳理它的特点、常用方法,以及和其他相关集合的关联,方便后续随时回顾知识点。

一、HashSet 集合的特点

(一)底层实现

HashSet 底层依托 HashMap 实现 。我们向 HashSet 添加元素时,实际是把元素作为 HashMapkey 存储,利用 HashMap key 不允许重复的特性,保证了 HashSet 元素的唯一性。

(二)元素特性

  • 无序性:无法保证元素的存储和取出顺序一致,元素在集合里是无序排列的,每次遍历结果顺序可能不同 。
  • 唯一性 :集合中不能存在重复元素,这由底层 HashMap 保障。
  • 允许 null 值 :集合元素值可以为 null,不过只能有一个 null 元素,毕竟 HashMapkey 虽能为 null,但也得唯一。
  • 线程不安全 :在多线程环境下,若多个线程同时操作 HashSet,可能引发数据不一致问题,需额外做线程同步处理。

二、HashSet 常用方法

(一)添加元素:add (Object o)

用于向 HashSet 集合添加元素,若元素已存在,不会重复添加,返回 false;添加成功返回 true 。示例代码:

java 复制代码
HashSet<String> set = new HashSet<>();
set.add("Java");
set.add("Python");
set.add("Java"); // 重复元素,添加失败

(二)获取元素个数:size ()

返回 HashSet 集合中当前元素的数量 。示例:

java 复制代码
HashSet<String> set = new HashSet<>();
set.add("Java");
set.add("Python");
System.out.println(set.size()); // 输出 2

(三)删除元素:remove (Object o)

删除集合中指定的 obj 对象,删除成功返回 true,元素不存在则返回 false 。代码示例:

java 复制代码
HashSet<String> set = new HashSet<>();
set.add("Java");
set.add("Python");
System.out.println(set.remove("Python")); // 输出 true,删除成功
System.out.println(set.remove("C++")); // 输出 false,元素不存在

(四)判断是否为空:isEmpty ()

HashSet 不包含任何元素,返回 true,否则返回 false 。示例:

java 复制代码
HashSet<String> set = new HashSet<>();
System.out.println(set.isEmpty()); // 输出 true
set.add("Java");
System.out.println(set.isEmpty()); // 输出 false

(五)清空集合:clear ()

移除 HashSet 中的所有元素,执行后集合为空 。示例:

java 复制代码
HashSet<String> set = new HashSet<>();
set.add("Java");
set.add("Python");
set.clear();
System.out.println(set.isEmpty()); // 输出 true

(六)迭代器遍历:iterator ()

返回一个在此 HashSet 元素上进行迭代的迭代器,借助迭代器可遍历集合元素 。示例:

java 复制代码
HashSet<String> set = new HashSet<>();
set.add("Java");
set.add("Python");
Iterator<String> ite = set.iterator();
while (ite.hasNext()) {
    System.out.println(ite.next());
}

(七)判断元素是否存在:contains (Object o)

用于判断集合中是否包含指定的 obj 元素,存在返回 true,不存在返回 false 。示例:

java 复制代码
HashSet<String> set = new HashSet<>();
set.add("Java");
System.out.println(set.contains("Java")); // 输出 true
System.out.println(set.contains("C++")); // 输出 false

(八)增强 for 循环遍历

通过增强 for 循环(foreach)可便捷遍历 HashSet 集合中的元素 。示例:

java 复制代码
HashSet<String> set = new HashSet<>();
set.add("Java");
set.add("Python");
for (String element : set) {
    System.out.println(element);
}

三、与其他集合的关联及使用场景对比

(一)与 LinkedHashSet

LinkedHashSet 底层基于 HashSet,同时用链表维护元素插入顺序。它兼具 HashSet 元素唯一的特性,又能保证元素有序(按插入顺序) 。若需元素唯一且顺序和插入一致,选 LinkedHashSet;追求添加、查询高性能,无需顺序,用 HashSet

(二)与 TreeSet

TreeSet 内部用 TreeMap(基于红黑树实现),会对插入数据排序(自然排序或定制排序),元素唯一、值不能为 null 且线程不安全 。若需对元素排序,用 TreeSet;仅需元素唯一、无序,HashSet 更高效。

(三)与 List 集合(以区别角度看)

  • 有序性List(如 ArrayListLinkedList )保证按插入顺序排序,Set(包括 HashSet )存储和取出顺序通常不一致 。
  • 唯一性List 允许元素重复,SetHashSet 等)元素唯一 。
  • 元素操作List 可通过索引直接操作元素,SetHashSet )不能根据索引获取元素 。

四、总结

HashSet 在 Java 集合框架里,凭借底层 HashMap 实现,实现了元素唯一、无序等特性,常用方法能满足基本集合操作需求。和 LinkedHashSetTreeSetList 集合各有适用场景,实际开发中,我们要依据元素是否需排序、是否要顺序、是否允许重复等需求,合理选择集合,让代码更高效、更贴合业务逻辑。掌握 HashSet ,能为我们处理数据集合相关问题筑牢基础,后续也可结合更多复杂场景,深入挖掘它的潜力 。