1. 概述

本文将探讨如何将 Java 中的 Collection 作为参数传递给可变参数(varargs)方法。我们将分析多种实现方式,并对比它们的优缺点。

2. 什么是可变参数?

可变参数(varargs)是 Java 5 引入的特性,通过方法参数类型后的三个点(...)标识:

public void method(String... strings) {}

核心特性:允许向方法传递任意数量的同类型参数。例如:

method(s1, s2, s3);

底层实现:JVM 会自动创建数组并填充传入的参数。

3. 问题场景

当参数是独立变量时,调用 varargs 方法很简单。但实际开发中,我们常遇到参数已封装在集合中的情况。假设我们有:

List<String> listOfStrings = List.of(s1, s2, s3);

现在需要将这个 List 传递给 varargs 方法。以下是几种解决方案:

4. 传统 for 循环填充数组

通过传统 for 循环将集合元素复制到数组,再传递给方法:

@Test
void givenList_whenUsingForLoopToPopulateArray_thenInvokeVarargsMethod() {
    String[] array = new String[listOfStrings.size()];
    for (int i = 0; i < listOfStrings.size(); i++) {
        array[i] = listOfStrings.get(i);
    }
    assertDoesNotThrow(() -> method(array));
}

优缺点分析

  • ✅ 逻辑直观,适合初学者理解
  • 踩坑警告:仅适用于有序集合(如 List),对 Set 等无序集合无效
  • ❌ 代码冗长,不够简洁

5. 使用 Collection.toArray() 方法

所有 Collection 子类都必须实现 toArray() 方法。推荐使用 toArray(T[] a) 重载方法

@Test
void givenList_whenUsingCollectionToArray_thenInvokeVarargsMethod() {
    assertDoesNotThrow(() -> method(listOfStrings.toArray(new String[0])));
}

进阶写法(Java 11+):

method(listOfStrings.toArray(String[]::new));

关键优势

  • 简单粗暴:一行代码搞定转换
  • ✅ 类型安全:无需强制转换
  • ✅ 适用于所有 Collection 子类型(包括 Set
  • ⚠️ 注意:避免使用无参 toArray(),它返回 Object[] 需要类型转换

6. 使用 Stream.toArray() 方法

通过 Stream API 的终端操作 toArray() 实现转换:

@Test
void givenList_whenUsingStreamAPI_thenInvokeVarargsMethod() {
    String[] array = listOfStrings.stream().toArray(String[]::new);
    assertDoesNotThrow(() -> method(array));
}

适用场景

  • ✅ 需要元素过滤或转换时(配合 filter()/map()
  • ✅ 函数式编程风格
  • ❌ 简单场景略显繁琐
  • ❌ 性能略低于直接 toArray()(Stream 创建开销)

7. 总结

方法 适用场景 代码简洁度 性能 灵活性
for 循环 有序集合 ⭐⭐ ⭐⭐⭐
Collection.toArray() 通用场景 ⭐⭐⭐ ⭐⭐⭐⭐
Stream.toArray() 需要数据处理 ⭐⭐ ⭐⭐

核心建议

  1. 优先使用 collection.toArray(T[]::new) —— 简洁高效
  2. 需要元素处理时再考虑 Stream API
  3. 避免手动循环实现(除非特殊需求)

本文所有代码示例可在 GitHub 获取。


原始标题:Pass Collection as Varargs Argument | Baeldung