When I run the following code, no output is printed.
int[] array = {3, 2, 5, 4};
if (Arrays.asList(array).contains(3))
{
System.out.println("The array contains 3");
}
When I run the following code, no output is printed.
int[] array = {3, 2, 5, 4};
if (Arrays.asList(array).contains(3))
{
System.out.println("The array contains 3");
}
When you pass an array of primitives (int[]
in your case) to Arrays.asList
, it creates a List<int[]>
with a single element - the array itself. Therefore contains(3)
returns false. contains(array)
would return true.
If you'll use Integer[]
instead of int[]
, it will work.
Integer[] array = {3, 2, 5, 4};
if (Arrays.asList(array).contains(3))
{
System.out.println("The array contains 3");
}
A further explanation :
The signature of asList
is List<T> asList(T...)
. A primitive can't replace a generic type parameter. Therefore, when you pass to this method an int[]
, the entire int[]
array replaces T
and you get a List<int[]>
. On the other hand, when you pass an Integer[]
to that method, Integer
replaces T
and you get a List<Integer>
.
In Java 8, you don't need to convert the array at all; just turn it into a stream via Arrays#stream
, then use the anyMatch
predicate to see if the value you want is contained in the array.
int[] array = {3, 2, 5, 4};
if (Arrays.stream(array).anyMatch(x -> x == 3)) {
System.out.println("The array contains 3");
}
The previous answer explains why your approach does not work.
To achieve what you like, you can also use Apache Commons Lang utilities like this:
import org.apache.commons.lang.ArrayUtils;
...
int[] array = {3, 2, 5, 4};
ArrayUtils.contains(array, 3);
Arrays.asList(T... a)
takes a T[]
for any object type T
which will match any array of objects (i.e., things that subclass of Object
). The only things that won't match is an array of primitives, since primitive types do not derive from Object
. That is, an int[]
is not a (subclass of) Object[]
.
What happens then is that the varags mechanism kicks in and treats it as if you had passed a single object, and creates a single element array of that type. So you pass an int[][]
(here, T
is int[]
) and end up with a 1-element List<int[]>
which is not what you want.
You still have some pretty good options though:
Int.asList(int[])
AdapterIf your project already uses guava, it's as simple as using the adapter Guava provides: Int.asList(). There is a similar adapter for each primitive type in the associated class, e.g., Booleans
for boolean
, etc.
Your function could be written as:
int[] array = {3, 2, 5, 4};
if (Ints.asList(array).contains(3))
{
System.out.println("The array contains 3");
}
The advantage of this approach is that it creates a thin wrapper around the existing array, so the creation of the wrapper is constant time (doesn't depend on the size of the array), and the storage required is only a small constant amount (less than 100 bytes) in addition to the underlying integer array.
The downside is that accessing each element requires a boxing operation of the underlying int
, and setting requires unboxing. This may result in a large amount of transient memory allocation if you access the list heavily. In your toy example, there will be only one boxing operation during the search, since the element is found immediately. Similarly, algorithms like binary search which only sparsely access the array are likely to perform reasonably.
If, however, you access each object many times on average, it may be better to use an implementation that boxes the objects once and stores them as Integer
. That can be as simple as making a copy of the list: new ArrayList<>(Ints.asList(array))
, or you in Java 8 you can use the IntStream.boxed()
approach (described below) to create a List<Integer>
. Both should perform about equally.
As described in Makato's answer, you can use the Arrays.stream(int[])
method to turn an int
array into a Stream
. Depending on your use case, you may be able to use the stream directly, e.g., to determine if the element 3
exists, you can use IntStream.anyMatch()
. In that case, this solution is very fast and doesn't incur any boxing or unboxing at all, and does not create any copy of the underlying array.
Alternately, if you really need a List<Integer>
, you can use stream.boxed().collect(Collectors.toList())
as suggested here. The downside of that approach is that it fully boxes every element in the list, which might increase its memory footprint by nearly an order of magnitude, it create a new Object[]
to hold all the boxed elements. If you subsequently use the list heavily and need Integer
objects rather than int
s, this may pay off, but it's something to be aware of.