1. 概述

本文将探讨如何将基本类型数组(如 int[])转换为对应包装类型的 List(如 List<Integer>。你可能会第一时间想到 Java 的自动装箱(autoboxing)机制。但正如接下来要展示的,这种直觉往往是错的,直接使用会导致编译失败。

✅ 核心问题:Java 的 autoboxing 只适用于单个元素,不支持整个基本类型数组到包装类型数组的自动转换


2. 问题分析

假设我们有如下代码:

int[] input = new int[]{1, 2, 3, 4};
List<Integer> output = Arrays.asList(input);

我们期望 Arrays.asList() 能通过 autoboxing 自动把 int[] 转成 List<Integer>。但现实很骨感——编译直接报错:

incompatible types: inference variable T has incompatible bounds
    equality constraints: java.lang.Integer 
    lower bounds: int[]

⚠️ 原因:Arrays.asList(T...) 中的 T 必须是引用类型,而 int[] 是一个“基本类型数组”,它会被当作 Integer 的“下界不匹配”对象处理,无法装箱。

换句话说:

  • intInteger:自动装箱 ✔️
  • int[]Integer[]不会自动发生

所以,我们必须手动解决这个类型转换问题。


3. 手动遍历(最原始但可靠)

既然自动装箱只对单个元素有效,那我们就老老实实遍历数组,逐个添加:

int[] input = new int[]{1, 2, 3, 4};
List<Integer> output = new ArrayList<>();
for (int value : input) {
    output.add(value); // 自动装箱在这里生效
}

✅ 优点:逻辑清晰,兼容所有 Java 版本
❌ 缺点:代码啰嗦,不够优雅

适合对性能敏感或不能用 Java 8 的老项目。但如果你用的是现代 Java,有更好的方式。


4. 使用 Stream API(推荐方式)

从 Java 8 开始,Stream 提供了简洁的解决方案:

int[] input = new int[]{1, 2, 3, 4};
List<Integer> output = Arrays.stream(input)
    .boxed()
    .collect(Collectors.toList());

或者使用 IntStream.of

List<Integer> output = IntStream.of(input)
    .boxed()
    .collect(Collectors.toList());

🔍 解释:

  • Arrays.stream(input) 返回的是 IntStream
  • .boxed() 将每个 int 装箱为 Integer
  • collect(Collectors.toList()) 收集为 List<Integer>

✅ 优点:一行搞定,函数式风格,简洁明了
💡 小贴士:在实际开发中这是最常用、最推荐的方式


5. 使用 Guava 库(第三方利器)

Google 的 Guava 提供了专门处理基本类型数组的工具类。

先加依赖:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>

然后直接调用 Ints.asList()

int[] input = new int[]{1, 2, 3, 4};
List<Integer> output = Ints.asList(input);

⚠️ 注意:这个 List只读视图(backed by the original array),不能调用 add()remove(),否则抛 UnsupportedOperationException

✅ 优点:代码极简,性能好
❌ 缺点:返回的是不可变 List,需注意使用场景

其他类型也有对应工具类:

  • Longs.asList(long[])
  • Doubles.asList(double[])
  • Booleans.asList(boolean[])

6. 使用 Apache Commons Lang

另一个常用库是 Apache Commons Lang

添加依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

使用 ArrayUtils.toObject() 先转成包装数组,再用 Arrays.asList()

int[] input = new int[]{1, 2, 3, 4};
Integer[] outputBoxed = ArrayUtils.toObject(input);
List<Integer> output = Arrays.asList(outputBoxed);

✅ 优点:转换结果是标准 List,可修改(取决于 asList 行为)
⚠️ 注意:Arrays.asList() 返回的 List 也不能扩容(add 会报错),但可以修改元素值

如果需要可变 List,建议包装一层:

List<Integer> output = new ArrayList<>(Arrays.asList(outputBoxed));

7. 总结

方法 是否推荐 说明
手动遍历 ⚠️ 仅兼容老版本 原始但可靠
Stream API ✅ 强烈推荐 简洁、现代、通用
Guava ✅ 推荐 极简,但注意返回的是只读 List
Apache Commons ✅ 可选 需额外依赖,适合已引入项目的场景

💡 最佳实践建议

  • 新项目首选 Stream 方式,简单粗暴无副作用
  • 已使用 Guava 的项目可用 Ints.asList(),注意只读限制
  • 别再试图用 Arrays.asList(int[]),那是踩坑的开始

示例代码已上传至 GitHub:https://github.com/baeldung/core-java-collections


原始标题:Convert an Array of Primitives to a List | Baeldung