一、Set 接口基础
(一)特点
-
用于存放任意 `Object` 对象。
-
无序:元素存储顺序与添加顺序无关。
-
无下标:不能通过索引访问元素。
-
元素不能重复:判断重复基于元素内容(而非地址),如两个内容相同的 `String` 对象会被视为重复元素。
(二)方法
仅继承自 `Collection` 父接口的所有方法,无独有方法。
(三)实现类
最常用的实现类是 `HashSet`,此外还有 `LinkedHashSet`、`TreeSet` 等。
二、HashSet 详解
(一)元素去重原理
当向 `HashSet` 中添加自定义类型对象时,需通过以下两个方法保证元素内容不重复:
- 覆盖 `hashCode()` 方法
- 原则:内容相同的对象需返回相同哈希码;为提高效率,内容不同的对象尽量返回不同哈希码。
- 覆盖 `equals()` 方法
- 原则:内容相同的对象返回 `true`,此时该对象不会被插入到 `Set` 集合中。
(二)存储机制(底层数组 + 哈希运算)
-
获取存储下标:`对象哈希码值 % 底层数组长度`。
-
哈希码值:由对象内存地址转化而来(默认情况)。
-
存储逻辑:
-
若存储位置为空,直接存入对象。
-
若存储位置已有元素,调用 `equals()` 方法判断内容是否相同:
-
若 `equals()` 返回 `true`(内容相同),拒绝添加。
-
若 `equals()` 返回 `false`(内容不同),则添加元素。
(三)代码示例
java
HashSet<String> set = new HashSet<String>();
String s1 = new String("Tom");
String s2 = new String("Liucy");
String s3 = new String("Huxz");
String s4 = new String("Jerry");
String s5 = new String("Jerry");
set.add(s1);
set.add(s2);
set.add(s3);
boolean bn1 = set.add(s4);
System.out.println("s4的插入结果:" + bn1); // 输出 true
boolean bn2 = set.add(s5);
System.out.println("s5的插入结果:" + bn2); // 输出 false
三、Set 集合遍历
支持 forEach 遍历,语法与 `List` 一致:
java
Set<String> set = new HashSet<String>();
set.add("lili");
set.add("hamei");
set.add("tom");
// forEach 遍历
for (String s : set) {
System.out.println(s);
}
// 自遍历(利用 forEach 方法)
set.forEach((s) -> {
System.out.println(s);
});
四、Set 其他实现类
(一)LinkedHashSet
-
是 `HashSet` 的子类。
-
特点:按元素添加顺序存储。
-
去重要求:与 `HashSet` 相同,需覆盖 `hashCode()` 和 `equals()` 方法。
-
遍历方式:支持 forEach 遍历、自遍历。
(二)TreeSet
-
是 `SortedSet` 接口的实现类(`SortedSet` 是 `Set` 的子接口)。
-
特点:可对集合元素自动排序(需元素实现 `Comparable` 接口或自定义比较器)。
-
遍历方式:支持 forEach 遍历、自遍历。