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]
我正在使用这样的参数调用方法: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]