Java HashSet 使用Set.of构建不可变去重集合

作者:技术拾光时间:2026-07-21 08:03:08浏览:418

Set.of创建不可变集合,自动去重但非HashSet,不允许null及修改。若需不可变HashSet,须先构建HashSet再封装或使用Guava的ImmutableSet。注意Set.of是Java9引入的,其内部基于数组,元素顺序不确定,适用于少量固定数据,效率高且不可变,不是HashSet,无哈希特性,但保证唯一性。

Set.of 本质是不可变集合,不是HashSet

在Java开发中,Set.of 和 HashSet 经常被放在一起讨论,但很多人容易混淆它们的本质区别。简单来说:Set.of 创建的是不可变集合,虽然自带去重,但它并不是基于 HashSet 实现的,也绝不允许修改或传入 null。如果你想要一个“不可变的 HashSet”,就得先手动构建一个 HashSet,再套一层不可变封装,或者直接用 Guava 的 ImmutableSet。

Java HashSet 使用Set.of构建不可变去重集合

Set.of 创建的是不可变集合,它本身不基于 HashSet 实现,也不支持重复元素(自动去重),但你不能通过它“构建 HashSet”——因为 Set.of 返回的是不可变的 Set 实现类(如 ImmutableSet),而非 HashSet 实例。

Set.of(...) 是 Java 9 引入的工厂方法,返回一个轻量级、不可修改的 Set。它的底层实现根据元素个数选择不同类(比如 0–10 个元素用内部静态类,更多时用 ImmutableCollections.SetN),但绝不是 HashSet。它不接受 null,不允许添加/删除/修改,且自动去重——重复元素会被忽略,只保留一个。

  • Set.of("a", "b", "a") → 包含 "a" 和 "b"(去重成功)
  • Set.of("a", "b", "a").add("c") → 抛出 UnsupportedOperationException
  • Set.of("a", "b", "a") instanceof HashSet → false

如果需要不可变 + 基于 HashSet 的语义,得手动转换

假设你明确需要一个“底层行为类似 HashSet”的不可变集合——比如哈希查找、无序、允许自定义对象需重写 hashCode/equals——那不能直接用 Set.of 得到 HashSet,但可以走两条路:

  • 先用 new HashSet(...) 构建可变集合(完成去重和初始化)
  • 再用 Collections.unmodifiableSet(...) 封装为不可变视图
  • 或者使用 Guava 的 ImmutableSet.copyOf(...)(更安全,真正不可变)

示例:

Set immutable = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "b", "a")));

Set.of 的去重规则和限制

它按 equals 判断重复,要求所有元素非 null,且必须满足 equals/hashCode 合约。对自定义类,仍需正确重写这两个方法;否则去重可能失效。

  • 重复字面量(如 "hello")会自动合并
  • 两个不同对象但 equals 为 true → 视为重复,只留其一
  • 传入 null → 直接抛 NullPointerException

什么时候该用 Set.of?

它适合创建小规模、固定、已知内容的不可变去重集合,比如配置常量、枚举替代、临时校验集合等。轻量、线程安全、创建快。但如果你需要动态构建、大集合,或者想控制 HashSet 特有的容量、负载因子,那还是老老实实用 new HashSet 加不可变封装吧。