true
:int[] array = {1, 2};
System.out.println(Arrays.asList(array).contains(1));
true
:int[] array = {1, 2};
System.out.println(Arrays.asList(array).contains(1));
当泛型被擦除并且可变参数被转换时,方法 Arrays.asList(T ...)
实际上等同于类型为 Arrays.ofList(Object[])
的方法(它是同一方法的二进制等效物,JDK 1.4 版本)。
原始类型数组是一个 Object
(参见 this question),但不是一个 Object[]
,因此编译器认为您正在使用可变参数版本,并在您的 int 数组周围生成一个 Object 数组。您可以通过添加额外的步骤来说明发生了什么:
int[] array = {1, 2};
List<int[]> listOfArrays = Arrays.asList(array);
System.out.println(listOfArrays.contains(1));
这段代码可以编译通过,和你的代码等价。但是它显然会返回 false。
编译器将 varargs 调用转换为带有单个数组的调用,因此使用参数 T t1, T t2, T t3
调用期望参数为 T ...
的 varargs 方法等同于使用 new T[]{t1, t2, t3}
进行调用。但是特殊情况是,如果方法需要一个对象数组,那么原始类型的 varargs 将在创建数组之前自动装箱。因此,编译器认为 int 数组被传递为单个 Object,并创建一个元素类型为 Object[]
的单元素数组,将其传递给 asList()
。
所以这里再次展示上面的代码,展示编译器内部的实现方式:
int[] array = {1, 2};
// no generics because of type erasure
List listOfArrays = Arrays.asList(new Object[]{array});
System.out.println(listOfArrays.contains(1));
以下是使用int值调用Arrays.asList()
的好坏方式:
// These versions use autoboxing (which is potentially evil),
// but they are simple and readable
// ints are boxed to Integers, then wrapped in an Object[]
List<Integer> good1 = Arrays.asList(1,2,3);
// here we create an Integer[] array, and fill it with boxed ints
List<Integer> good2 = Arrays.asList(new Integer[]{1,2,3});
// These versions don't use autoboxing,
// but they are very verbose and not at all readable:
// this is awful, don't use Integer constructors
List<Integer> ugly1 = Arrays.asList(
new Integer(1),new Integer(2),new Integer(3)
);
// this is slightly better (it uses the cached pool of Integers),
// but it's still much too verbose
List<Integer> ugly2 = Arrays.asList(
Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3)
);
// And these versions produce compile errors:
// compile error, type is List<int[]>
List<Integer> bad1 = Arrays.asList(new int[]{1,2,3});
// compile error, type is List<Object>
List<Integer> bad2 = Arrays.asList(new Object[]{1,2,3});
参考资料:
但是,为了以简单的方式解决您的问题:
在Apache Commons / Lang(请参见Bozho's answer)和Google Guava中有一些库解决方案:
Ints.contains(int[], int)
检查int数组是否包含给定的intInts.asList(int ...)
从int数组创建一个整数列表Integer[]
也是一个对象。 - aioobeObject[]
,这更匹配。 - Sean Patrick FloydArrays.asList(array)
将会得到一个 int[]
的单例列表。
如果你将 int[]
改成 Integer[]
,它会如你所期望的工作。不知道这是否对您有帮助。
Arrays.asList(ArrayUtils.toObjectArray(array))
(ArrayUtils
来自 commons-lang)
但是,如果您只想调用 contains
,则不需要这样做。只需使用 Arrays.binarySearch(..)
(首先对数组进行排序)。
这个
System.out.println(Arrays.asList(array).contains(array));
返回true
。
看起来你对 Arrays.asList(T... a)
的理解是错误的。你不会是第一个对它的工作方式做出假设的人。
试着用它:
System.out.println(Arrays.asList(1, 2).contains(1));
自动装箱在这种情况下并不按照您的期望工作。以下代码可能有点冗长,但可以将int数组转换为列表:
List<Integer> list = new ArrayList<Integer>(array.length);
for (int value : array) {
list.add(value);
}
Integer[] array = {1, 2};
System.out.println(Arrays.asList(array).contains(1));
你的版本失败了,因为Int不是对象,但Int[]是一个对象。因此,你将使用一个元素作为Collection调用asList(T... a),因为不可能有一个Collection a。
int[] array = {1, 2};
List<Integer> list = IntStream.of(array).boxed().toList();
System.out.println(list.contains(1)); // true
Stream.toList()
返回的列表是不可变的。 - user16320675Arrays.asList()
使用提供的数组来支持列表,因此只有在搜索时才会迭代,就像您所建议的那样。 - Sean Patrick Floyd当你调用时
Arrays.asList(array)