Arrays.asList(int [])不起作用

时间:2015-07-15 05:18:02

标签: java arrays list

运行以下代码时,不会输出任何输出。

int[] array = {3, 2, 5, 4};

if (Arrays.asList(array).contains(3))
{
    System.out.println("The array contains 3");
}

3 个答案:

答案 0 :(得分:51)

当您将基本数组(在您的情况下为Arrays.asList)传递给List<int[]>时,它会创建一个带有单个元素的contains(3) - 数组本身。因此contains(array)返回false。 Integer[]将返回true。

如果您使用int[]代替Integer[] array = {3, 2, 5, 4}; if (Arrays.asList(array).contains(3)) { System.out.println("The array contains 3"); } ,则可以使用。

asList

进一步解释:

List<T> asList(T...)的签名是int[]。基元不能替换泛型类型参数。因此,当您将int[]传递给此方法时,整个T数组将替换List<int[]>,并获得Integer[]。另一方面,当您将Integer传递给该方法时,T会替换List<Integer>并获得{{1}}。

答案 1 :(得分:17)

在Java 8中,您根本不需要转换数组;只需通过Arrays#stream将其转换为流,然后使用anyMatch谓词查看所需的值是否包含在数组中。

int[] array = {3, 2, 5, 4};

if (Arrays.stream(array).anyMatch(x -> x == 3)) {
    System.out.println("The array contains 3");
}

答案 2 :(得分:-1)

Arrays.asList(T... a)为任何对象类型T[]提供T,它将匹配任何对象数组(即Object的子类)。唯一不匹配的是基元数组,因为基元类型不是从Object派生的。也就是说,int[]不是Object[]的(子类)。

然后发生的是,varags机制启动并将其视为传递单个对象,并创建该类型的单个元素数组。因此,您传递int[][](此处,Tint[])并最终得到1个元素List<int[]>,这不是您想要的。

你仍然有一些不错的选择:

Guava的Int.asList(int[])适配器

如果您的项目已经使用了番石榴,那就像使用Guava提供的适配器一样简单:Int.asList()。相关类中的每种基本类型都有一个类似的适配器,例如,Booleans用于boolean等。

您的功能可以写成:

int[] array = {3, 2, 5, 4};
if (Ints.asList(array).contains(3))
{
    System.out.println("The array contains 3");
}

这种方法的优点是它在现有数组周围创建了一个瘦包装器,因此包装器的创建是恒定时间(不依赖于数组的大小),并且所需的存储空间很小除了基础整数数组之外的常量(小于100个字节)。

缺点是访问每个元素需要底层int的装箱操作,并且设置需要拆箱。如果您大量访问列表,这可能会导致大量的瞬态内存分配。在您的玩具示例中,搜索期间将只有一个装箱操作,因为该元素立即被找到。类似地,只能稀疏地访问数组的二进制搜索等算法可能会合理地执行。

但是,如果平均多次访问每个对象,最好使用一次将对象装箱并将其存储为Integer的实现。这可以像制作列表的副本一样简单:new ArrayList<>(Ints.asList(array)),或者在Java 8中,您可以使用IntStream.boxed()方法(如下所述)来创建List<Integer>。两者都应该大致相同。

Java 8 IntStream

如Makato的answer所述,您可以使用Arrays.stream(int[])方法将int数组转换为Stream。根据您的使用情况,您可以直接使用流,例如,确定元素3是否存在,您可以使用IntStream.anyMatch()。在这种情况下,这个解决方案非常快,根本不会产生任何装箱或拆箱,并且不会创建底层阵列的任何副本。

或者,如果确实需要List<Integer>,则可以将stream.boxed().collect(Collectors.toList())用作suggested here。这种方法的缺点是它完全封装了列表中的每个元素,这可能会使其内存占用量增加近一个数量级,它会创建一个新的Object[]来保存所有盒装元素。如果您随后大量使用该列表并且需要Integer个对象而不是int s,这可能会有所回报,但这是值得注意的。