Java 9 集合工厂方法(千字长文)

Java 9 集合工厂方法:让集合创建更简洁优雅

在 Java 8 之后,集合的创建方式逐渐变得丰富,但依然存在一些“繁琐”的问题。比如,我们经常需要这样写代码:

List<String> list = new ArrayList<>();
list.add("苹果");
list.add("香蕉");
list.add("橙子");

虽然逻辑清晰,但写起来总觉得“多此一举”。尤其是在初始化少量元素时,这种写法显得格外啰嗦。而从 Java 9 开始,Oracle 引入了一个非常实用的新特性——集合工厂方法(Collection Factory Methods),它彻底改变了我们创建集合的方式。

这组方法不仅让代码更简洁,还带来了性能和可读性的双重提升。今天,我们就来深入聊聊这个让 Java 开发者“眼前一亮”的特性。


什么是集合工厂方法?

集合工厂方法是 Java 9 中新增的一组静态方法,它们位于 java.util 包下的 ListSetMap 接口里。这些方法允许我们通过一行代码就创建出不可变的集合实例。

所谓“不可变”,就是指创建后无法修改。比如不能添加、删除或替换元素。这在某些场景下非常有用,比如配置项、常量集合、传参时防止意外修改等。

想象一下:你有一个天气预报程序,需要存储全国主要城市的名称。这些城市列表是固定的,不会变化。这时候,使用不可变集合就能避免误操作,保证数据安全。


创建不可变列表:List.of() 方法详解

Java 9 为 List 接口提供了 of() 静态工厂方法,用于快速创建不可变的列表。

用法示例

// 创建一个包含 3 个元素的不可变列表
List<String> cities = List.of("北京", "上海", "广州");

// 直接打印输出
System.out.println(cities); // 输出: [北京, 上海, 广州]

✅ 注释:List.of() 是一个静态方法,不需要 new 实例。它返回一个不可变的 List 实例。
✅ 注释:参数可以是任意数量的元素(0 到 10 个),超过 10 个会抛出异常(但 Java 9 限制为最多 10 个,Java 10+ 才支持更多)。

支持的类型

该方法支持任意引用类型,如 StringInteger、自定义对象等:

List<Integer> numbers = List.of(1, 2, 3, 4, 5);
List<Person> people = List.of(
    new Person("张三", 25),
    new Person("李四", 30)
);

✅ 注释:List.of() 不接受 null 值,如果传入 null 会抛出 NullPointerException
✅ 注释:如果需要创建空列表,请使用 List.of() 本身(不传参数)或 List.of() 的变体。

注意事项

  • 不能调用 add()remove() 等修改方法,否则会抛出 UnsupportedOperationException
  • 如果你确实需要可变集合,可以使用 new ArrayList<>(List.of(...)) 转换。

创建不可变集合:Set.of() 方法

List.of() 类似,Set.of() 用于创建不可变的集合(Set),它会自动去重。

示例代码

// 创建一个不可变的 Set,自动去重
Set<String> uniqueColors = Set.of("红色", "蓝色", "绿色", "红色");

System.out.println(uniqueColors); // 输出: [红色, 蓝色, 绿色]

✅ 注释:Set.of() 接收多个参数,自动忽略重复元素,保证集合的唯一性。
✅ 注释:如果元素中包含 null,会抛出 NullPointerException,不支持 null

实际应用场景

假设你正在开发一个权限管理系统,用户角色只能是以下几种:

Set<String> validRoles = Set.of("管理员", "编辑", "查看者");

这个集合一旦创建,就不会被外部修改,确保系统逻辑的稳定性。


创建不可变映射:Map.of() 与 Map.ofEntries()

Map 接口提供了两个工厂方法:Map.of()Map.ofEntries(),用于创建不可变的键值对映射。

Map.of():适合少量键值对

// 创建一个不可变的 Map,键值对以成对形式传入
Map<String, Integer> scoreMap = Map.of(
    "数学", 95,
    "语文", 88,
    "英语", 92
);

System.out.println(scoreMap); // 输出: {数学=95, 语文=88, 英语=92}

✅ 注释:Map.of() 最多支持 10 个键值对。如果超过 10 个,会抛出 IllegalArgumentException
✅ 注释:键和值都不能为 null,否则会抛出 NullPointerException

Map.ofEntries():支持更多键值对

当需要创建超过 10 个键值对时,可以使用 Map.ofEntries(),它接受 Map.Entry 类型的参数:

// 使用 Map.ofEntries() 支持更多元素
Map<String, String> config = Map.ofEntries(
    Map.entry("host", "localhost"),
    Map.entry("port", "8080"),
    Map.entry("timeout", "3000"),
    Map.entry("debug", "true")
);

System.out.println(config); // 输出: {host=localhost, port=8080, timeout=3000, debug=true}

✅ 注释:Map.entry()Map 接口提供的静态方法,用于创建键值对对象。
✅ 注释:Map.ofEntries() 支持任意数量的键值对,没有数量限制。


Java 9 集合工厂方法 vs 传统方式对比

特性 传统方式(new ArrayList<>) Java 9 集合工厂方法
代码长度 长(需多行) 短(一行搞定)
可变性 默认可变 默认不可变
性能 需要实例化、调用 add() 内部优化,更高效
空值支持 支持 null 不支持 null
适用场景 需要动态修改集合时 配置、常量、只读数据

✅ 注释:工厂方法在创建时就确定了内容,无需扩容,性能更优。
✅ 注释:虽然不可变集合不能修改,但可以通过 List.copyOf() 等方法转换为可变集合。


实际项目中的最佳实践

在实际开发中,合理使用 Java 9 的集合工厂方法,能显著提升代码质量。

场景一:配置常量

public class AppConfig {
    // 使用不可变集合存储配置
    public static final Set<String> SUPPORTED_LANGUAGES = Set.of("zh", "en", "ja", "ko");
    public static final Map<String, String> DEFAULT_HEADERS = Map.of(
        "Content-Type", "application/json",
        "User-Agent", "MyApp/1.0"
    );
}

✅ 注释:这些配置在程序运行期间不会改变,使用不可变集合更安全。

场景二:方法参数传递

public void processOrders(List<Order> orders) {
    // 传入一个不可变列表,防止内部被修改
    List<Order> safeOrders = List.of(orders.toArray(new Order[0]));
    // 处理逻辑...
}

✅ 注释:即使外部传入的是可变集合,我们也可以通过工厂方法创建一份“安全副本”。


常见问题与注意事项

1. 为什么不能包含 null?

因为不可变集合的设计目标是“安全”和“简洁”。如果允许 null,在后续使用中可能引发 NullPointerException,破坏了“不可变”的语义。

2. 无法修改集合,怎么办?

如果需要修改,可以先用工厂方法创建不可变集合,再转换为可变集合:

List<String> immutable = List.of("A", "B", "C");
List<String> mutable = new ArrayList<>(immutable);
mutable.add("D"); // 现在可以修改了

3. 工厂方法是否线程安全?

是的,不可变集合本身就是线程安全的,因为它们的内容从不改变。多个线程共享同一个 List.of() 返回的实例是安全的。


总结:为什么你该用 Java 9 集合工厂方法?

Java 9 集合工厂方法并不是一个“炫技”的功能,而是一个真正能提升开发效率和代码质量的实用工具。它让集合创建变得更简单、更安全、更高效。

  • 代码更简洁,减少样板代码;
  • 避免误操作,提升程序稳定性;
  • 性能更优,内部做了优化;
  • 更符合现代编程中“不可变性”的设计思想。

尤其对于初学者来说,掌握这些方法能让你的代码看起来更“专业”;对于中级开发者,它能帮助你在项目中写出更健壮、更易维护的代码。

所以,从现在开始,不要再写 new ArrayList<>() + 一堆 add() 了。试试 List.of()Set.of()Map.of() 吧。你会发现,Java 的世界,其实可以更简洁。

最后提醒一句:如果你还在用 Java 8 或更早版本,建议尽快升级到 Java 9 或更高版本,以获得这些实用的语法糖支持。毕竟,写代码,本就不该那么累。