Arrays.asList(T... a)
有效地T[]
将匹配任何真实对象数组(的子类Object
)的 a 作为数组。唯一不匹配的是基元数组,因为基元类型不是从Object
. 所以 anint[]
不是Object[]
.
然后发生的事情是 varags 机制启动并将其视为您传递了单个对象,并创建了该类型的单个元素数组。因此,您传递了一个int[][]
(此处T
为 is int[]
)并最终得到一个 1 元素List<int[]>
,这不是您想要的。
不过,您仍然有一些不错的选择:
番石榴的Int.asList(int[])
适配器
如果您的项目已经使用了番石榴,那么它就像使用 Guava 提供的适配器一样简单: Int.asList()。关联类中的每个原始类型都有一个类似的适配器,例如Booleans
forboolean
等。
int foo[] = {1,2,3,4,5};
Iterable<Integer> fooBar = Ints.asList(foo);
for(Integer i : fooBar) {
System.out.println(i);
}
这种方法的优点是它在现有数组周围创建了一个瘦包装器,因此包装器的创建是常数时间(不依赖于数组的大小),并且所需的存储量只是一个很小的常数(小于 100 字节)以及底层整数数组。
缺点是访问每个元素需要对底层进行装箱操作int
,设置需要拆箱。如果您频繁访问列表,这可能会导致大量的临时内存分配。如果您平均多次访问每个对象,则最好使用将对象装箱一次并将它们存储为Integer
. 下面的解决方案就是这样做的。
Java 8 内部流
在 Java 8 中,您可以使用该Arrays.stream(int[])
方法将int
数组转换为Stream
. 根据您的用例,您可以直接使用流,例如,对每个元素使用forEach(IntConsumer)
. 在这种情况下,此解决方案非常快,根本不会产生任何装箱或拆箱,并且不会创建底层数组的任何副本。
或者,如果你真的需要一个List<Integer>
,你可以stream.boxed().collect(Collectors.toList())
按照这里的建议使用。这种方法的缺点是它完全装箱了列表中的每个元素,这可能会增加它的内存占用近一个数量级,它会创建一个新Object[]
的来保存所有装箱的元素。如果您随后大量使用列表并需要Integer
对象而不是int
s,这可能会得到回报,但需要注意这一点。