Arrays.asList(int )不工作

当我运行以下代码时,不打印输出。

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

将基本数组(在您的情况下为int[] )传递给Arrays.asList ,它会创建一个List其中包含一个元素 – 数组本身。 因此contains(3)返回false。 contains(array)将返回true。

如果你将使用Integer[]而不是int[] ,它将起作用。

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

进一步说明:

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

在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"); } 

之前的答案解释了为什么您的方法不起作用。

要实现您的喜好,您还可以使用Apache Commons Lang实用程序:

 import org.apache.commons.lang.ArrayUtils; ... int[] array = {3, 2, 5, 4}; ArrayUtils.contains(array, 3); 

Arrays.asList(T... a)有效地获取T[] ,它将匹配任何真实对象数组( Object子类)作为数组。 唯一不匹配的是基元数组,因为基本类型不是从Object派生的。 所以int[]不是Object[]

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

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

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

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

您的function可以写成:

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

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

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

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

Java 8 IntStream

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

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