1. 概述
本文将系统介绍在 Java 中创建 HashSet 时如何同时初始化元素的多种方法,适合需要快速查阅初始化技巧的开发者。
如果你更关注 HashSet 本身的特性(比如性能、去重机制等),可以参考我们另一篇核心文章:Java HashSet 详解。
我们将从以下几个方面展开:
✅ Java 5 及更早版本提供的原生方式
✅ Java 8 引入 Stream 后的新玩法
✅ 自定义工具方法提升复用性
✅ 第三方集合库(如 Google Guava)的优雅方案
✅ JDK9+ 用户的简单选择:集合工厂方法
💡 提示:如果你的项目已经升级到 JDK9 或更高版本,最简单粗暴的方式其实是直接使用
Set.of("a", "b", "c")
。但本文重点覆盖低版本 JDK 的兼容方案,适用于尚未升级的项目。
2. Java 原生方法(Java 5 及之前)
以下是三种从 Java 5 就支持的初始化方式,无需额外依赖。
2.1 使用已有集合实例
通过构造函数传入另一个集合(如 List),是最常见且安全的方式之一。
Set<String> set = new HashSet<>(Arrays.asList("a", "b", "c"));
✅ 优点:简洁、无性能陷阱
⚠️ 注意:Arrays.asList()
返回的是固定大小的 List,不能增删,但这里只是用于初始化 HashSet,没问题
2.2 匿名内部类 + 实例初始化块(双大括号)
利用匿名类和实例初始化块(double brace)语法:
Set<String> set = new HashSet<String>(){{
add("a");
add("b");
add("c");
}};
❌ 踩坑警告:
- 每次调用都会创建一个新的匿名类,增加类加载开销
- 序列化时可能导致问题(携带外部类引用)
- 性能敏感场景务必避免
📌 结论:虽然写起来爽,但属于“看起来很美”的反模式,生产环境慎用。
2.3 使用 Collections 工具类(单元素场景)
Java 提供了 Collections.singleton(T obj)
方法,用于快速创建只含一个元素的不可变 Set:
Set<String> set = Collections.singleton("a");
✅ 适用场景:
- 单元测试中 mock 返回值
- 配置常量、标志位等固定单值
⚠️ 注意:返回的是 immutable Set,调用 add()
会抛 UnsupportedOperationException
3. 自定义工具方法
如果项目中频繁需要创建带初始值的 HashSet,建议封装一个泛型工具方法。
public static final <T> Set<T> newHashSet(T... objs) {
Set<T> set = new HashSet<>();
Collections.addAll(set, objs);
return set;
}
使用方式:
Set<String> set = newHashSet("a", "b", "c");
✅ 优势分析:
- ✅ 支持变长参数,调用简洁
- ✅ 使用
Collections.addAll
,底层是数组拷贝,效率高 - ✅ 泛型设计,类型安全
- ✅ 返回可变 Set,后续可修改
💡 建议:把这个方法放在项目的 CollectionUtils
或 Sets
工具类中,团队共用。
4. 使用 Stream(Java 8+)
Java 8 引入 Stream 后,可以通过 Stream.of
+ Collectors.toCollection
实现灵活初始化:
Set<String> set = Stream.of("a", "b", "c")
.collect(Collectors.toCollection(HashSet::new));
✅ 优势:
- 可结合 filter、map 等操作做预处理
- 函数式风格,适合链式调用
- 易于扩展(比如从数组/数据库记录构建)
❌ 缺点:
- 相比直接构造略重,小数据量无感,高频调用需权衡
🎯 适用场景:需要对数据做转换或过滤后再构建成 Set 的情况。
5. 使用第三方集合库
5.1 Google Guava
Guava 是 Java 社区最流行的集合扩展库之一,Maven 依赖如下:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>
创建可变 Set
Set<String> set = Sets.newHashSet("a", "b", "c");
创建不可变 Set(推荐用于常量)
Set<String> set = ImmutableSet.of("a", "b", "c");
✅ Guava 优势:
- API 设计优雅,命名清晰
- ImmutableSet 性能优于 Collections.unmodifiableSet
- 提供更多高级集合操作(差集、交集等)
📌 社区共识:Guava 的 ImmutableSet 是创建不可变集合的事实标准。
5.2 其他可选库
- Apache Commons Collections:
CollectionUtils
工具丰富,但初始化语法不如 Guava 直观 - Eclipse Collections:函数式风格更强,适合大数据处理场景
推荐优先考虑 Guava,生态成熟,文档齐全。
6. 总结与建议
方式 | 适用版本 | 是否可变 | 推荐程度 | 场景建议 |
---|---|---|---|---|
new HashSet<>(Arrays.asList()) |
Java 5+ | ✅ 可变 | ⭐⭐⭐⭐ | 通用初始化,无依赖 |
双大括号初始化 | Java 5+ | ✅ 可变 | ⭐ | ❌ 避免生产使用 |
Collections.singleton() |
Java 5+ | ❌ 不可变 | ⭐⭐⭐ | 单元素场景 |
自定义 newHashSet() |
Java 5+ | ✅ 可变 | ⭐⭐⭐⭐⭐ | 团队项目首选 |
Stream + Collectors |
Java 8+ | ✅ 可变 | ⭐⭐⭐⭐ | 需预处理数据时 |
Guava Sets.newHashSet() |
Java 8+ | ✅ 可变 | ⭐⭐⭐⭐⭐ | 有 Guava 依赖时 |
Guava ImmutableSet.of() |
Java 8+ | ❌ 不可变 | ⭐⭐⭐⭐⭐ | 常量、配置项 |
🔚 最终建议:
- **JDK9+**:优先使用
Set.of(...)
(不可变)或new HashSet<>(List.of(...))
(可变)- 低版本 JDK:封装工具方法 or 引入 Guava
- 避免双大括号,别为了少写两行代码埋下性能坑
所有示例代码均已上传至 GitHub:https://github.com/baeldung/core-java-modules/tree/master/core-java-collections-set