Arrays.Aslist() of an Array

Difference between Arrays.asList(array) and new ArrayListInteger(Arrays.asList(array))

  1. First, let's see what this does:

    Arrays.asList(ia)

    It takes an array ia and creates a wrapper that implements List<Integer>, which makes the original array available as a list. Nothing is copied and all, only a single wrapper object is created. Operations on the list wrapper are propagated to the original array. This means that if you shuffle the list wrapper, the original array is shuffled as well, if you overwrite an element, it gets overwritten in the original array, etc. Of course, some List operations aren't allowed on the wrapper, like adding or removing elements from the list, you can only read or overwrite the elements.

    Note that the list wrapper doesn't extend ArrayList - it's a different kind of object. ArrayLists have their own, internal array, in which they store their elements, and are able to resize the internal arrays etc. The wrapper doesn't have its own internal array, it only propagates operations to the array given to it.

  2. On the other hand, if you subsequently create a new array as

    new ArrayList<Integer>(Arrays.asList(ia))

    then you create new ArrayList, which is a full, independent copy of the original one. Although here you create the wrapper using Arrays.asList as well, it is used only during the construction of the new ArrayList and is garbage-collected afterwards. The structure of this new ArrayList is completely independent of the original array. It contains the same elements (both the original array and this new ArrayList reference the same integers in memory), but it creates a new, internal array, that holds the references. So when you shuffle it, add, remove elements etc., the original array is unchanged.

Can I create a list of array with Arrays.asList?

No. Arrays.asList takes a projection of your current array and flattens the first dimension into a List. Since you only have one dimension, all of those elements get collected into the list.

You could do it if you had an Integer[][].

Note: asList accepts a vararg of T (so T...), which is effectively T[]. If you substitute that with Integer[][], you get Integer[], since one dimension of your Integer[][] will satisfy T...'s type requirement.

Arrays.asList() of an array

Let's consider the following simplified example:

public class Example {
public static void main(String[] args) {
int[] factors = {1, 2, 3};
ArrayList<Integer> f = new ArrayList(Arrays.asList(factors));
System.out.println(f);
}
}

At the println line this prints something like "[[I@190d11]" which means that you have actually constructed an ArrayList that contains int arrays.

Your IDE and compiler should warn about unchecked assignments in that code. You should always use new ArrayList<Integer>() or new ArrayList<>() instead of new ArrayList(). If you had used it, there would have been a compile error because of trying to pass List<int[]> to the constructor.

There is no autoboxing from int[] to Integer[], and anyways autoboxing is only syntactic sugar in the compiler, so in this case you need to do the array copy manually:

public static int getTheNumber(int[] factors) {
List<Integer> f = new ArrayList<Integer>();
for (int factor : factors) {
f.add(factor); // after autoboxing the same as: f.add(Integer.valueOf(factor));
}
Collections.sort(f);
return f.get(0) * f.get(f.size() - 1);
}

Create ArrayList from array

new ArrayList<>(Arrays.asList(array));

What is the best way of using Arrays.asList() to initialize a List

Case 2 is better performance-wise BUT: it returns a List with an immutable size. Meaning you cannot add/remove elements to/from it:

Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.)

Arrays#asList

Convert from Arrays.asList to Array

You can use flatMap instead of map and

Stream.of instead of Arrays.asList

Bson[] result = fieldsToFilter.stream()
.flatMap(e -> Stream.of(Filters.ne(e, "") , Filters.exists(e, true)))
.toArray(Bson[]::new);

Why does Arrays.asList(...).toArray().getClass() give different results in JDK 8 and 9?

The List type returned by asList is Arrays$ArrayList. The toArray method in JDK 8 on that class is:

@Override
public Object[] toArray() {
return a.clone();
}

But in JDK 9+ it is:

@Override
public Object[] toArray() {
return Arrays.copyOf(a, a.length, Object[].class);
}

In both cases a String[] is passed to asList, but in the JDK 8 case it is cloned, which retains its array type (String[]), and in JDK 9+ it is copied using Arrays.copyOf with the explicit new array type of Object[].

This difference means that in JDK 8 Arrays.asList("a", "b").toArray().getClass() returns String[] and in JDK 9+ it returns Object[], so in JDK 9+ your expression will evaluate to false.

The reason for this change comes from JDK-6260652 with the motivation:

The Collection documentation claims that

collection.toArray()

is "identical in function" to

collection.toArray(new Object[0]);

However, the implementation of Arrays.asList does not follow this: If created with an array of a subtype (e.g. String[]), its toArray() will return an array of the same type (because it use clone()) instead of an Object[].

If one later tries to store non-Strings (or whatever) in that array, an ArrayStoreException is thrown.

So this change was made to fix the previous behaviour.


If this is a problem for you, the related release note offers this as a work-around:

If this problem occurs, rewrite the code to use the one-arg form toArray(T[]), and provide an instance of the desired array type. This will also eliminate the need for a cast.

String[] array = list.toArray(new String[0]);

why list can't be initialized with array, without arrays.aslist()?

Indeed, Arrays.asList is implemented as you said, but ArrayList doesn't actually refer to the java.util.ArrayList that we all know and love. It refers to a private inner class in the Arrays class. From the first link, just under the declaration of asList, you will see:

/**
* @serial include
*/
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
...

new ArrayList<>(a) is referring to the above class. The above class has a constructor that takes an E[]:

    ArrayList(E[] array) {
if (array==null)
throw new NullPointerException();
a = array;
}

But the java.util.ArrayList class doesn't have such a constructor, so it is no wonder that you can't do:

List<String> list = new ArrayList<>(new String[]{"hello", "world"});

Another big difference between java.util.ArrayList and java.util.Arrays$ArrayList is that you can add/remove elements to the former, but you can't to the latter. e.g. This throws an exception:

Arrays.asList("a", "b", "c").add("d");

Using Arrays.asList with int array

List cannot hold primitive values because of java generics (see similar question). So when you call Arrays.asList(ar) the Arrays creates a list with exactly one item - the int array ar.

EDIT:

Result of Arrays.asList(ar) will be a List<int[]>, NOT List<int> and it will hold one item which is the array of ints:

[ [1,2,3,4,5] ]

You cannot access the primitive ints from the list itself. You would have to access it like this:

list.get(0).get(0) // returns 1
list.get(0).get(1) // returns 2
...

And I think that's not what you wanted.



Related Topics



Leave a reply



Submit