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 包下的 List、Set 和 Map 接口里。这些方法允许我们通过一行代码就创建出不可变的集合实例。
所谓“不可变”,就是指创建后无法修改。比如不能添加、删除或替换元素。这在某些场景下非常有用,比如配置项、常量集合、传参时防止意外修改等。
想象一下:你有一个天气预报程序,需要存储全国主要城市的名称。这些城市列表是固定的,不会变化。这时候,使用不可变集合就能避免误操作,保证数据安全。
创建不可变列表: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+ 才支持更多)。
支持的类型
该方法支持任意引用类型,如 String、Integer、自定义对象等:
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 或更高版本,以获得这些实用的语法糖支持。毕竟,写代码,本就不该那么累。