Difference between Arrays.asList(array) and new ArrayListInteger(Arrays.asList(array))
First, let's see what this does:
Arrays.asList(ia)
It takes an array
ia
and creates a wrapper that implementsList<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, someList
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.ArrayList
s 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.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 usingArrays.asList
as well, it is used only during the construction of the newArrayList
and is garbage-collected afterwards. The structure of this newArrayList
is completely independent of the original array. It contains the same elements (both the original array and this newArrayList
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[]
), itstoArray()
will return an array of the same type (because it useclone()
) instead of anObject[]
.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 int
s:
[ [1,2,3,4,5] ]
You cannot access the primitive int
s 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
How to Set Up Default Schema Name in JPA Configuration
Comparing the Values of Two Generic Numbers
How to Use Collections.Sort() in Java
How to Create an Instance of Inner Class Using Java Reflection
Equivalent of Waitforvisible/Waitforelementpresent in Selenium Webdriver Tests Using Java
List All Files in the Folder and Also Sub Folders
Possible to Use Two Java Classes with Same Name and Same Package
Class Object of Generic Class (Java)
How to Select an Item from a Dropdown List Using Selenium Webdriver with Java
How to Get a List of Trusted Root Certificates in Java
How to Dynamically Create a Test Suite in Junit 4
Cannot Assign Requested Address Using Serversocket.Socketbind
Attach the Source in Eclipse of a Jar
Invalid Signature File Digest for Manifest Main Attributes Exception While Trying to Run Jar File