在Java中集合初始化有哪些常见写法_Java集合创建方式解析

Java集合初始化无唯一推荐方式:需据不可变性、Java版本等选择;Arrays.asList()返回固定大小列表,List.of()(Java9+)创建真正不可变集合,传统new+add最兼容。

Java 中集合初始化没有“唯一推荐方式”,选哪种取决于你是否需要不可变性、是否要立即赋值、是否在 Java 版本受限环境(如 Java 8)、以及是否在意对象创建开销。

Arrays.asList() 快速初始化但要注意它是固定大小的

Arrays.asList() 是最常被误用的初始化方式。它返回的是 java.util.Arrays$ArrayList,不是 java.util.ArrayList,不支持 add()remove() —— 调用会抛 UnsupportedOperationException

适用场景:临时传参、只读遍历、测试数据构造。

  • 如果后续要修改,必须包装成可变集合:new ArrayList(Arrays.asList("a", "b"))
  • 泛型推断在 Java 8+ 可省略类型,但 Java 7 需写全:Arrays.asList("x", "y")
  • 不能传原始类型数组(如 int[]),否则整个数组会被当做一个元素;要用 Integer[]
List list = new ArrayList<>(Arrays.asList("foo", "bar")); // 安全可变
List nums = Arrays.asList(1, 2, 3); // 不可增删

Java 9+ 推荐用 List.of()Set.of() 创建不可变集合

这些是真正不可变(immutable)的集合,线程安全、内存紧凑、构造快。但一旦创建就不能修改,也不能含 null 元素——含 null 会直接抛 NullPointerException

注意:它们不是 ArrayListHashSet 的子类,而是私有内部实现类,toString() 输出格式也不同(如 List.of(1,2) 打印为 [1, 2],但底层不是 ArrayList)。

  • 元素个数超过 10 个时,需改用变参重载版本(如 List.of(a,b,c,...) 最多支持 10 个参数)
  • 若需要 null 支持或可变性,别硬套,老实用 new ArrayList() + add()
  • 性能上比 Arrays.asList() + 包装更轻量,适合配置项、枚举集合等静态数据
List constants = List.of("HTTP", "HTTPS");
Set codes = Set.of(200, 404, 500);

传统方式:先声明再 add(),兼容所有 Java 版本

这是最稳妥、最易理解的方式,适用于任何 Java 版本,且完全可控。缺点是代码稍长,尤其初始化多个元素时。

常见错误是忘记指定泛型(导致编译警告),或误用原始类型(如 new ArrayList() 而非 new ArrayList())。

  • 可以配合容量预估减少扩容:例如 new ArrayList(16)
  • 链式调用需借助匿名内部类或工具类(如 Guava 的 ImmutableList.bui

    lder()
    ),但原生 Java 不支持
  • 若只是单次初始化且后续只读,不如直接用 List.of()(Java 9+)或 Arrays.asList()(需确认不可变需求)
ArrayList list = new ArrayList<>();
list.add("first");
list.add("second");
list.add("third");

静态工厂方法或工具类封装适合高频重复初始化

当项目中反复出现相同结构的集合(如 HTTP 状态码映射、协议白名单),硬编码每次初始化既啰嗦又难维护。这时应抽成静态方法或常量。

不要在每个使用点都写一遍 Arrays.asList(...) 或一堆 add(),尤其当元素可能变化时——分散初始化等于埋雷。

  • private static final 声明不可变集合(Java 9+ 优先用 List.of()
  • 若需可变副本,提供一个工厂方法:createDefaultConfig() 返回新实例
  • 避免在静态块里做复杂逻辑(如 IO、反射),影响类加载速度
public class Config {
    public static final List SUPPORTED_SCHEMES = List.of("http", "https", "file");
    
    public static List createMutableSchemes() {
        return new ArrayList<>(SUPPORTED_SCHEMES);
    }
}

真正容易被忽略的点是:不可变集合的“不可变”仅指接口行为,不保证其元素本身不可变。比如 List.of(new StringBuilder("a")),虽然列表不能增删,但里面的 StringBuilder 仍可被修改。需要深层不可变,得靠设计约束或使用不可变数据结构(如 Immutables、Vavr)。