Java 9 的 Set.of() 返回高度优化的不可变实现类(如 ImmutableCollections.SetN),元素存于 final 数组,构造时即校验 null 和重复,零对象膨胀,仅适用于小规模编译期已知场景。

Java 9 的 Set.of() 不是简单包装一个普通 HashSet,而是直接返回高度定制的不可变实现类(如 ImmutableCollections.SetN),专为小规模、固定内容场景深度优化。它省去了哈希表扩容、桶数组分配、键值对封装等开销,内存结构极紧凑——元素直接存于私有 final 数组中,无额外引用层级。
构造即校验,杜绝运行时隐患
不同于旧方式(如 Collections.unmodifiableSet(new HashSet(...)))在运行时才暴露问题,Set.of() 在调用瞬间就完成两项关键检查:
- 任一参数为
null,立即抛出NullPointerException - 任意两个参数
equals()相等(即逻辑重复),立即抛出IllegalArgumentException
这种“fail-fast at construction”机制把错误拦截在源头,避免无效集合流入业务流程。
零对象膨胀,轻量级只读语义
传统包装方式会生成至少两层对象:底层可变集合 + 外层不可变视图。而 Set.of() 返回的是单个、无状态、无代理的终态对象:
立即学习“Java免费学习笔记(深入)”;
- 不持有任何可变字段,无需同步或 volatile 修饰
- 所有方法(
contains()、size()、iterator())都基于 final 数组直接实现,无委托开销 - JVM 可对其做标量替换(scalar replacement)和逃逸分析优化,部分实例甚至可完全栈分配
适用边界清晰,不强行替代通用集合
它不是万能集合,设计初衷明确:
- 适合元素数 ≤10、内容编译期可知的场景,例如枚举值白名单:
Set.of("GET", "POST", "PUT") - 不适合动态构建、含上百元素或需自定义比较器的集合——此时应选
TreeSet或 Guava 的ImmutableSet - 注意:集合本身不可变,但若元素是可变对象(如
StringBuilder),其内部状态仍可被修改
这套机制让小型常量集合从“语法糖”升级为“性能原语”,既安全又高效。


















