Arrays.asList(int [])不工作[重复]

Posted

技术标签:

【中文标题】Arrays.asList(int [])不工作[重复]【英文标题】:Arrays.asList(int[]) not working [duplicate] 【发布时间】:2015-10-03 23:58:55 【问题描述】:

当我运行以下代码时,没有输出任何输出。

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

if (Arrays.asList(array).contains(3))

    System.out.println("The array contains 3");

【问题讨论】:

【参考方案1】:

当您将基元数组(在您的情况下为int[])传递给Arrays.asList 时,它会创建一个带有单个元素的List<int[]> - 数组本身。因此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<T> asList(T...)。原语不能替换泛型类型参数。因此,当您将int[] 传递给此方法时,整个int[] 数组将替换T,您将获得List<int[]>。另一方面,当您将Integer[] 传递给该方法时,Integer 将替换T,您将获得List<Integer>

【讨论】:

【参考方案2】:

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

【讨论】:

比Arrays.asList好吗? @GyuHyeonChoi:我认为它是等价的。数组和列表在 O(n) 中运行以查找单个元素。这只是消除了创建用于调用便捷方法的对象的额外开销。 那一定更好!我会更好地使用更新的函数流吗?【参考方案3】:

The previous answer 解释了为什么您的方法不起作用。

要实现你喜欢的,你也可以使用Apache Commons Lang这样的工具:

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

【讨论】:

这不是让它工作的好方法。您也没有完全解释问题。 @haywire:为什么它不是让它工作的好方法?因为 Apache 一般都是坏东西? 将第三方库用于语言(或其标准库)本身已经可以实现的东西是不好的做法。如果您将 ACL 实用程序用于 Java 无法做到的事情,那确实是有意义的。【参考方案4】:

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

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

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

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

如果您的项目已经使用了 guava,那么只需使用 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 内部流

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

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

【讨论】:

不要复制your answer,而是将此问题标记为重复。 我将其标记为受骗者:***.com/questions/10335662/…。无论如何,重复的问题通常会一直存在,因此值得在这里获得高质量的答案。我还更新了我的答案以与 OP 的特定用例(在数组中搜索)和该案例的性能考虑保持一致。此外,我链接到现有的相关答案并提供了更多详细信息。 “我将其标记为欺骗” 嗯,有趣的问题。但我猜另一个问题(你的第一个答案)有更好的标题,使用搜索引擎会更容易找到。您已经更新了已经很好的答案以匹配 OPs 案例并不能防止这个问题重复出现,并且非常不喜欢一遍又一遍地回答同一个问题,尤其是在复制答案的情况下 (meta)。 我认为“工作错误”的标题是错误的并且难以搜索。事实上 asList 工作正常。真正的问题是如何将原始数组视为列表或集合。 OP 的问题只是反映了一种错误的信念,即 Arrays.asList 可以做到。

以上是关于Arrays.asList(int [])不工作[重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用Arrays.asList方法使用Stream打印int数组[复制]

Arrays.asList使用误区

List中的Arrays.asList()

Arrays.asList(int_array).indexOf(int_element) 即使元素存在java也返回-1 [重复]

浅谈Arrays.asList()方法的使用

数组的 Arrays.asList()