在 Java 开发中,List 是最常用的集合类型之一。如何优雅且高效地初始化它,往往取决于具体场景。下面梳理了五种常见的初始化方案,并分析了各自的优缺点和潜在陷阱。
1. 构造后逐个添加
这是最基础的方式,逻辑直观但代码冗余。
List<String> stringList = new LinkedList<>();
stringList.add("a");
stringList.add("b");
stringList.add("c");
适合需要动态判断是否添加元素的场景,但在已知常量数据时显得不够简洁。
2. 双括号语法
利用匿名内部类和实例初始化块,可以一行完成初始化。
List<String> stringList = new LinkedList<String>(){{
add("a");
add("b");
add("c");
}};
虽然写法紧凑,但底层会生成一个匿名内部类。这带来两个隐患:一是性能损耗,每次创建都会多出一个类文件;二是内存泄漏风险,静态内部类可能持有外部类的引用。除非对性能极其敏感或确定不会返回给外部,否则生产环境慎用。
3. Arrays.asList
借助 java.util.Arrays 的静态方法,代码非常简洁。
List<String> stringList = Arrays.asList("a", "b", "c");
返回的是 Arrays 的内部实现类,支持随机访问,但不支持增删操作。如果试图调用 add 或 remove,会抛出 UnsupportedOperationException。因此,它更适合用于定义不可变常量列表。
另外要注意基本类型数组的陷阱。如果传入 int[],返回值是 List<int[]> 而不是 List。
int[] intArray = new int[]{1, 2, 3};
List<int[]> intArrayList = Arrays.asList(intArray); // 注意这里是 int[] 对象
建议尽量使用包装类型,避免底层数组带来的类型混淆。
4. Stream API (JDK8+)
利用流式处理进行收集。
List<String> list = Stream.of("a", "b", "c").collect(Collectors.toList());
功能强大,适合复杂转换场景。但对于简单的常量初始化,略显'杀鸡用牛刀',且 Collectors.toList() 在某些版本中返回的可变列表行为需留意。
5. 工具类辅助
许多开发框架或库提供了便捷的工厂方法,例如 Guava 的 Lists。

