This may be a bit of an easy, headdesk sort of question, but my first attempt surprisingly completely failed to work. I wanted to take an array of primitive longs and turn it into a list, which I attempted to do like this:
long[] input = someAPI.getSomeLongs();
List<Long> inputAsList = Arrays.asList(input); //Total failure to even compile!
What\'s the right way to do this?
I found it convenient to do using apache commons lang ArrayUtils (JavaDoc, Maven dependency)
import org.apache.commons.lang3.ArrayUtils;
...
long[] input = someAPI.getSomeLongs();
Long[] inputBoxed = ArrayUtils.toObject(input);
List<Long> inputAsList = Arrays.asList(inputBoxed);
it also has the reverse API
long[] backToPrimitive = ArrayUtils.toPrimitive(objectArray);
EDIT: updated to provide a complete conversion to a list as suggested by comments and other fixes.
hallidave and jpalecek have the right idea—iterating over an array—but they don\'t take advantage of a feature provided by ArrayList
: since the size of the list is known in this case, you should specify it when you create the ArrayList
.
List<Long> list = new ArrayList<Long>(input.length);
for (long n : input)
list.add(n);
This way, no unnecessary arrays are created only to be discarded by the ArrayList
because they turn out to be too short, and no empty \"slots\" are wasted because ArrayList
overestimated its space requirements. Of course, if you continue to add elements to the list, a new backing array will be needed.
A bit more verbose, but this works:
List<Long> list = new ArrayList<Long>();
for (long value : input) {
list.add(value);
}
In your example it appears that Arrays.asList() is interpreting the input as list of long[] arrays instead of a list of Longs. A bit surprising, for sure. Autoboxing just doesn\'t work the way you want it to in this case.
You can use transmorph :
Transmorph transmorph = new Transmorph(new DefaultConverters());
List<Long> = transmorph.convert(new long[] {1,2,3,4}, new TypeReference<List<Long>>() {});
It also works if source is an array of ints for example.
I know this question is old enough, but... you can also write your own conversion method:
@SuppressWarnings(\"unchecked\")
public static <T> List<T> toList(Object... items) {
List<T> list = new ArrayList<T>();
if (items.length == 1 && items[0].getClass().isArray()) {
int length = Array.getLength(items[0]);
for (int i = 0; i < length; i++) {
Object element = Array.get(items[0], i);
T item = (T)element;
list.add(item);
}
} else {
for (Object i : items) {
T item = (T)i;
list.add(item);
}
}
return list;
}
After you include it using static import, possible usages could be:
long[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<Long> list = toList(array);
or
List<Long> list = toList(1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l, 9l);
The question asked about how to turn an array into a list. Most answers so far showed how to create a new list with the same contents as the array, or referred to third-party libraries. However, there are simple, built-in options for this sort of conversion. Some of them have already been sketched in other answers (e.g. this one). But I\'d like to point out and elaborate certain degrees of freedom for the implementation here, and show the potential benefits, drawbacks and caveats.
There are at least two important distinctions to be made:
- Whether the resulting list should be a view on the array or whether it should be a new list
- Whether the resulting list should be modifiable or not
The options will be summarized here quickly, and a complete example program is shown at the bottom of this answer.
Creating a new list versus creating a view on the array
When the result should be a new list, then one of the approaches from the other answers may be used:
List<Long> list = Arrays.stream(array).boxed().collect(Collectors.toList());
But one should consider the drawbacks of doing this: An array with 1000000 long
values will occupy roughly 8 Megabytes of memory. The new list will also occupy roughly 8 Megabytes. And of course, the full array has to be traversed while creating this list. In many cases, creating a new list is simply not necessary. Instead, it is sufficient to create a view on the array:
// This occupies ca. 8 MB
long array[] = { /* 1 million elements */ }
// Properly implemented, this list will only occupy a few bytes,
// and the array does NOT have to be traversed, meaning that this
// operation has nearly ZERO memory- and processing overhead:
List<Long> list = asList(array);
(See the example at the bottom for an implementation of the toList
method)
The implication of having a view on the array are that changes in the array will be visible in the list:
long array[] = { 12, 34, 56, 78 };
List<Long> list = asList(array);
System.out.println(list.get(1)); // This will print 34
// Modify the array contents:
array[1] = 12345;
System.out.println(list.get(1)); // This will now print 12345!
Fortunately, creating a copy (that is, a new list that is not affected by modifications in the array) from the view is trivial:
List<Long> copy = new ArrayList<Long>(asList(array));
Now, this is a true copy, equivalent to what is achieved with the stream-based solution that was shown above.
Creating a modifiable view or an unmodifiable view
In many cases, it will be sufficient when the list is read-only. The contents of the resulting list will often not be modified, but only passed to downstream processing that only reads the list.
Allowing for modifications of the list raises some questions:
long array[] = { 12, 34, 56, 78 };
List<Long> list = asList(array);
list.set(2, 34567); // Should this be possible?
System.out.println(array[2]); // Should this print 34567?
list.set(3, null); // What should happen here?
list.add(99999); // Should this be possible?
It is possible to create a list view on the array that is modifiable. This means that changes in the list, like setting a new value at a certain index, will be visible in the array.
But it is not possible to create a list view that is structurally modifiable. This means that it is not possible to do operations that affect the size of the list. This is simply because the size of the underlying array cannot be changed.
The following is a MCVE showing the different implementation options, and the possible ways of using the resulting lists:
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
public class PrimitiveArraysAsLists
{
public static void main(String[] args)
{
long array[] = { 12, 34, 56, 78 };
// Create VIEWS on the given array
List<Long> list = asList(array);
List<Long> unmodifiableList = asUnmodifiableList(array);
// If a NEW list is desired (and not a VIEW on the array), this
// can be created as well:
List<Long> copy = new ArrayList<Long>(asList(array));
System.out.println(\"array : \" + Arrays.toString(array));
System.out.println(\"list : \" + list);
System.out.println(\"unmodifiableList: \" + unmodifiableList);
System.out.println(\"copy : \" + copy);
// Modify a value in the array. The changes will be visible
// in the list and the unmodifiable list, but not in
// the copy.
System.out.println(\"Changing value at index 1 of the array...\");
array[1] = 34567;
System.out.println(\"array : \" + Arrays.toString(array));
System.out.println(\"list : \" + list);
System.out.println(\"unmodifiableList: \" + unmodifiableList);
System.out.println(\"copy : \" + copy);
// Modify a value of the list. The changes will be visible
// in the array and the unmodifiable list, but not in
// the copy.
System.out.println(\"Changing value at index 2 of the list...\");
list.set(2, 56789L);
System.out.println(\"array : \" + Arrays.toString(array));
System.out.println(\"list : \" + list);
System.out.println(\"unmodifiableList: \" + unmodifiableList);
System.out.println(\"copy : \" + copy);
// Certain operations are not supported:
try
{
// Throws an UnsupportedOperationException: This list is
// unmodifiable, because the \"set\" method is not implemented
unmodifiableList.set(2, 23456L);
}
catch (UnsupportedOperationException e)
{
System.out.println(\"Expected: \" + e);
}
try
{
// Throws an UnsupportedOperationException: The size of the
// backing array cannot be changed
list.add(90L);
}
catch (UnsupportedOperationException e)
{
System.out.println(\"Expected: \" + e);
}
try
{
// Throws a NullPointerException: The value \'null\' cannot be
// converted to a primitive \'long\' value for the underlying array
list.set(2, null);
}
catch (NullPointerException e)
{
System.out.println(\"Expected: \" + e);
}
}
/**
* Returns an unmodifiable view on the given array, as a list.
* Changes in the given array will be visible in the returned
* list.
*
* @param array The array
* @return The list view
*/
private static List<Long> asUnmodifiableList(long array[])
{
Objects.requireNonNull(array);
return new AbstractList<Long>()
{
@Override
public Long get(int index)
{
return array[index];
}
@Override
public int size()
{
return array.length;
}
};
}
/**
* Returns a view on the given array, as a list. Changes in the given
* array will be visible in the returned list, and vice versa. The
* list does not allow for <i>structural modifications</i>, meaning
* that it is not possible to change the size of the list.
*
* @param array The array
* @return The list view
*/
private static List<Long> asList(long array[])
{
Objects.requireNonNull(array);
return new AbstractList<Long>()
{
@Override
public Long get(int index)
{
return array[index];
}
@Override
public Long set(int index, Long element)
{
long old = array[index];
array[index] = element;
return old;
}
@Override
public int size()
{
return array.length;
}
};
}
}
The output of the example is shown here:
array : [12, 34, 56, 78]
list : [12, 34, 56, 78]
unmodifiableList: [12, 34, 56, 78]
copy : [12, 34, 56, 78]
Changing value at index 1 of the array...
array : [12, 34567, 56, 78]
list : [12, 34567, 56, 78]
unmodifiableList: [12, 34567, 56, 78]
copy : [12, 34, 56, 78]
Changing value at index 2 of the list...
array : [12, 34567, 56789, 78]
list : [12, 34567, 56789, 78]
unmodifiableList: [12, 34567, 56789, 78]
copy : [12, 34, 56, 78]
Expected: java.lang.UnsupportedOperationException
Expected: java.lang.UnsupportedOperationException
Expected: java.lang.NullPointerException