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[][]
(这里,T
是 int[]
)并最终得到一个 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
对象而不是 int
s,这可能会有所回报,但需要注意。
【讨论】:
不要复制your answer,而是将此问题标记为重复。 我将其标记为受骗者:***.com/questions/10335662/…。无论如何,重复的问题通常会一直存在,因此值得在这里获得高质量的答案。我还更新了我的答案以与 OP 的特定用例(在数组中搜索)和该案例的性能考虑保持一致。此外,我链接到现有的相关答案并提供了更多详细信息。 “我将其标记为欺骗” 嗯,有趣的问题。但我猜另一个问题(你的第一个答案)有更好的标题,使用搜索引擎会更容易找到。您已经更新了已经很好的答案以匹配 OPs 案例并不能防止这个问题重复出现,并且非常不喜欢一遍又一遍地回答同一个问题,尤其是在复制答案的情况下 (meta)。 我认为“工作错误”的标题是错误的并且难以搜索。事实上 asList 工作正常。真正的问题是如何将原始数组视为列表或集合。 OP 的问题只是反映了一种错误的信念,即Arrays.asList
可以做到。以上是关于Arrays.asList(int [])不工作[重复]的主要内容,如果未能解决你的问题,请参考以下文章
使用Arrays.asList方法使用Stream打印int数组[复制]
Arrays.asList(int_array).indexOf(int_element) 即使元素存在java也返回-1 [重复]