数据结构-HashSet
在 Java 编程的世界里,集合框架是极为重要的一部分,而 HashSet
作为 Set 接口的典型实现类,在处理不允许重复元素的场景中频繁亮相。今天,我们就一同深入探究 HashSet
,梳理它的特点、常用方法,以及和其他相关集合的关联,方便后续随时回顾知识点。
一、HashSet 集合的特点
(一)底层实现
HashSet
底层依托 HashMap
实现 。我们向 HashSet
添加元素时,实际是把元素作为 HashMap
的 key
存储,利用 HashMap
key
不允许重复的特性,保证了 HashSet
元素的唯一性。
(二)元素特性
- 无序性:无法保证元素的存储和取出顺序一致,元素在集合里是无序排列的,每次遍历结果顺序可能不同 。
- 唯一性:集合中不能存在重复元素,这由底层
HashMap
保障。 - 允许 null 值:集合元素值可以为
null
,不过只能有一个null
元素,毕竟HashMap
的key
虽能为null
,但也得唯一。 - 线程不安全:在多线程环境下,若多个线程同时操作
HashSet
,可能引发数据不一致问题,需额外做线程同步处理。
二、HashSet 常用方法
(一)添加元素:add (Object o)
用于向 HashSet
集合添加元素,若元素已存在,不会重复添加,返回 false
;添加成功返回 true
。示例代码:
HashSet<String> set = new HashSet<>();
set.add("Java");
set.add("Python");
set.add("Java"); // 重复元素,添加失败
(二)获取元素个数:size ()
返回 HashSet
集合中当前元素的数量 。示例:
HashSet<String> set = new HashSet<>();
set.add("Java");
set.add("Python");
System.out.println(set.size()); // 输出 2
(三)删除元素:remove (Object o)
删除集合中指定的 obj
对象,删除成功返回 true
,元素不存在则返回 false
。代码示例:
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
。示例:
HashSet<String> set = new HashSet<>();
System.out.println(set.isEmpty()); // 输出 true
set.add("Java");
System.out.println(set.isEmpty()); // 输出 false
(五)清空集合:clear ()
移除 HashSet
中的所有元素,执行后集合为空 。示例:
HashSet<String> set = new HashSet<>();
set.add("Java");
set.add("Python");
set.clear();
System.out.println(set.isEmpty()); // 输出 true
(六)迭代器遍历:iterator ()
返回一个在此 HashSet
元素上进行迭代的迭代器,借助迭代器可遍历集合元素 。示例:
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
。示例:
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
集合中的元素 。示例:
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
(如ArrayList
、LinkedList
)保证按插入顺序排序,Set
(包括HashSet
)存储和取出顺序通常不一致 。 - 唯一性:
List
允许元素重复,Set
(HashSet
等)元素唯一 。 - 元素操作:
List
可通过索引直接操作元素,Set
(HashSet
)不能根据索引获取元素 。
四、总结
HashSet
在 Java 集合框架里,凭借底层 HashMap
实现,实现了元素唯一、无序等特性,常用方法能满足基本集合操作需求。和 LinkedHashSet
、TreeSet
及 List
集合各有适用场景,实际开发中,我们要依据元素是否需排序、是否要顺序、是否允许重复等需求,合理选择集合,让代码更高效、更贴合业务逻辑。掌握 HashSet
,能为我们处理数据集合相关问题筑牢基础,后续也可结合更多复杂场景,深入挖掘它的潜力 。