java.lang.ArrayStoreException 用新元素扩展列表时

java.lang.ArrayStoreException when extending a list with new elements

我正在使用这样的参数调用方法:methodName(Object... param)。这些方法我不能改变。为了使我的代码更具动态性,我将列表传递给这些方法。就其本身而言,这不是问题,因为我可以调用:

methodName(list.toArray(new Object[]{}));

而且效果很好。但是,有时我需要将额外的元素传递给这些方法,但无法将这些项目添加到列表中。为此,我尝试了以下方法:

methodName(Arrays.asList(list, oobj1, obj2).toArray(new Object[]{}));

编译得很好。但是当调用它时,它会导致 java.lang.ArrayStoreException.

下面是一个完全复制此行为的示例代码。我尝试了多种变体,但 none 按预期工作。

List<Integer> nums = new ArrayList<>();
nums.add(1);
nums.add(2);
nums.add(3);

System.out.println(Arrays.asList(nums, 8, 9).toArray(new Integer[] {}));
System.out.println(Arrays.asList(nums.toArray(new Integer[] {}), 8, 9).toArray(new Integer[] {}));

Arrays.asList(nums, 8, 9) 单独导致 [[1, 2, 3], 8, 9]Arrays.asList(nums.toArray(new Integer[] {}), 8, 9) 导致 [[Ljava.lang.Integer;@15db9742, 8, 9].

所需的输出是 [1, 2, 3, 8, 9],无需更多代码。如何在保持初始列表不变的情况下实现此目的?

希望这就是您要找的:

Arrays.asList(mums, [8, 9]).stream()
    .flatMap(Collection::stream)
    .collect(<the collector you want>)

按照 Sweeper 的建议,我实现了一个效用函数。

代码现在

public static void main(String[] args) {
    List<Integer> nums = new ArrayList<>();
    nums.add(1);
    nums.add(2);
    nums.add(3);
    System.out.println(concat(7, nums, 4, 5, 6));
}
private <T> List<T> concat(T... nums) {
    List<T> result = new ArrayList<>();
    for (T t : nums) {
        if (t instanceof Collection)
            result.addAll((Collection<? extends T>) t);
        else
            result.add(t);
    }
    return result;
}

我不会在我的代码库中进行递归,因为我知道我不会在 nums 中嵌套另一个列表。然而,递归也可以很容易地实现,调用甚至不会改变:

static <T> List<T> concat(T... nums) {
    return concat(new ArrayList<>(), nums);
}

static <T> List<T> concat(List<T> result, T... nums) {
    for (T t : nums) {
        if (t instanceof Collection)
            concat(result, ((Collection<T>) t).toArray((T[]) new Object[] {}));
        else
            result.add(t);
    }
    return result;
}

总的来说,这种 concat 方法的优点是您可以同时添加和附加。您甚至可以连接多个列表并在列表之间添加元素。

三种方法(由 SgtOmer 添加了正确的 flatMap 方法):

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;
import java.util.stream.IntStream;

public class ArrayStore {
    public static void main(String[] args) {
        List<Integer> nums = new ArrayList<>();
        nums.add(1);
        nums.add(2);
        nums.add(3);

        System.out.println(Arrays.toString(
            Stream.concat(nums.stream(), IntStream.of(8, 9).boxed()).toArray(Integer[]::new)
        ));
        System.out.println(Arrays.toString(
            Stream.concat(nums.stream(), Stream.of(new Integer[]{8, 9})).toArray(Integer[]::new)
        ));
        System.out.println(Arrays.toString(
            Arrays.asList(nums, Arrays.asList(new Integer[]{8, 9})).stream().flatMap(Collection::stream).toArray(Integer[]::new)
        ));
    }
}

生产

$ java ArrayStore.java
[1, 2, 3, 8, 9]
[1, 2, 3, 8, 9]
[1, 2, 3, 8, 9]