Java HashSet
Set 存“不重复”的元素;HashSet 是 Set 最常用的实现,底层用 HashMap 存放元素,添加、删除、查找都很快,但不保证元素顺序。
特性与基本用法
Set 的特性:不重复(add 重复元素返回 false)且无序。元素没有下标,只能迭代(增强 for 底层是 Iterator)。常用方法 add / remove / contains / size / isEmpty / clear:
import java.util.HashSet;
public class HashSetDemo {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
System.out.println(set.add("苹果")); // 输出:true
System.out.println(set.add("苹果")); // 输出:false(重复被拒)
set.add("香蕉");
System.out.println(set); // 输出:[香蕉, 苹果](顺序不定)
for (String s : set) { // 增强 for 遍历
System.out.println(s);
}
System.out.println(set.contains("苹果")); // 输出:true
set.remove("苹果");
System.out.println(set.size()); // 输出:1
}
}
去重原理:hashCode 与 equals
HashSet 底层是 HashMap,元素作为“键”存放。判重先比 hashCode 定位、再用 equals 精确比较;两个内容相同的对象若没重写这两个方法,会被当成不同元素,去重就会失效。所以向 HashSet 存自定义对象,必须重写 equals 与 hashCode。借 HashSet 还能给 List 去重:new HashSet<>(list) 去重后再 new ArrayList<>(set) 转回(片段需放进 main 方法中运行)。
import java.util.HashSet;
import java.util.Objects;
class User {
String name;
User(String name) { this.name = name; }
@Override
public boolean equals(Object o) {
if (!(o instanceof User)) return false;
return Objects.equals(name, ((User) o).name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
public class UserDemo {
public static void main(String[] args) {
HashSet<User> set = new HashSet<>();
set.add(new User("张三"));
set.add(new User("张三")); // 内容相同,被去重
System.out.println(set.size()); // 输出:1
}
}
LinkedHashSet 与 TreeSet
两个变体:LinkedHashSet 去重但保持插入顺序;TreeSet 去重并按自然顺序升序排序。
import java.util.LinkedHashSet;
import java.util.TreeSet;
public class SubSetDemo {
public static void main(String[] args) {
LinkedHashSet<Integer> l = new LinkedHashSet<>();
l.add(3); l.add(1); l.add(2);
System.out.println(l); // 输出:[3, 1, 2](插入顺序)
TreeSet<Integer> t = new TreeSet<>();
t.add(3); t.add(1); t.add(2);
System.out.println(t); // 输出:[1, 2, 3](升序)
}
}
小结:HashSet 存不重复元素、查询快但无序,判重依赖 hashCode 与 equals;要保序用 LinkedHashSet、要排序用 TreeSet,都可以借助它给 List 去重。