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
。 基元不能替换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[][]
(这里, T
是int[]
)并最终得到一个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
,这可能会有所回报,但这是值得注意的。