Convert an array of primitive longs into a List of Longs

JavaArraysCollectionsBoxing

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

Since Java 8 you can now use streams for that:

long[] arr = { 1, 2, 3, 4 };
List<Long> list = Arrays.stream(arr).boxed().collect(Collectors.toList());

Solution 2 - Java

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.

Solution 3 - Java

import java.util.Arrays;
import org.apache.commons.lang.ArrayUtils;

List<Long> longs = Arrays.asList(ArrayUtils.toObject(new long[] {1,2,3,4}));

Solution 4 - Java

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.

Solution 5 - Java

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.

Solution 6 - Java

As another possibility, the Guava library provides this as Longs.asList(), with similar utility classes for the other primitive types.

import com.google.common.primitives.Longs;

long[] input = someAPI.getSomeLongs();
List<Long> output = Longs.asList(input);

Solution 7 - Java

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;
import java.util.RandomAccess;

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);
        class ResultList extends AbstractList<Long> implements RandomAccess
        {
            @Override
            public Long get(int index)
            {
                return array[index];
            }

            @Override
            public int size()
            {
                return array.length;
            }
        };
        return new ResultList();
    }
    
    /**
     * 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);
        class ResultList extends AbstractList<Long> implements RandomAccess
        {
            @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;
            }
        };
        return new ResultList();
    }
    
}

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

Solution 8 - Java

No, there is no automatic conversion from array of primitive type to array of their boxed reference types. You can only do

long[] input = someAPI.getSomeLongs();
List<Long> lst = new ArrayList<Long>();

for(long l : input) lst.add(l);

Solution 9 - Java

I'm writing a small library for these problems:

long[] input = someAPI.getSomeLongs();
List<Long> = $(input).toList();

In the case you care check it here.

Solution 10 - Java

Another way with Java 8.

long[] input = someAPI.getSomeLongs();
LongStream.of(input).boxed().collect(Collectors.toList()));

Solution 11 - Java

Another way with Java 8.

final long[] a = new long[]{1L, 2L};
final List<Long> l = Arrays.stream(a).boxed().collect(Collectors.toList());

Solution 12 - Java

Combining Pavel and Tom's answers we get this

   @SuppressWarnings("unchecked")
    public static <T> List<T> asList(final Object array) {
        if (!array.getClass().isArray())
            throw new IllegalArgumentException("Not an array");
        return new AbstractList<T>() {
            @Override
            public T get(int index) {
                return (T) Array.get(array, index);
            }

            @Override
            public int size() {
                return Array.getLength(array);
            }
        };
    }

Solution 13 - Java

If you want similar semantics to Arrays.asList then you'll need to write (or use someone else's) customer implementation of List (probably through AbstractList. It should have much the same implementation as Arrays.asList, only box and unbox values.

Solution 14 - Java

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.

Solution 15 - Java

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);

Solution 16 - Java

While it is possible to create a new List and add all the values to it (via for loop or streams), I have been working on really big arrays and get poor performance. Therefore I created my own easy to use primitive array wrapper class.

Example:

long[] arr = new long[] {1,2,3};
PrimativeList<Long> list = PrimativeList.create(arr); // detects long[] and returns PrimativeList<Long>

System.out.println(list.get(1)); // prints: 2
list.set(2, 15);
System.out.println(arr[2]);  // prints: 15

Get it here: https://github.com/Sf298/Sauds-Toolbox/blob/master/src/main/java/PrimitiveArrayWrapper/PrimitiveList.java

NOTE: I haven't fully tested it yet, so let me know if you find any bugs/issues.

Solution 17 - Java

You can use LongStream for that

List<Long> longs = LongStream.of(new long[]{1L, 2L, 3L}).boxed()
                             .collect(Collectors.toList());

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrandon YarbroughView Question on Stackoverflow
Solution 1 - JavamarcinjView Answer on Stackoverflow
Solution 2 - JavaEran MedanView Answer on Stackoverflow
Solution 3 - JavaMarco PelegriniView Answer on Stackoverflow
Solution 4 - JavaericksonView Answer on Stackoverflow
Solution 5 - JavahallidaveView Answer on Stackoverflow
Solution 6 - JavaTrevor RobinsonView Answer on Stackoverflow
Solution 7 - JavaMarco13View Answer on Stackoverflow
Solution 8 - JavajpalecekView Answer on Stackoverflow
Solution 9 - JavadfaView Answer on Stackoverflow
Solution 10 - JavaravenskaterView Answer on Stackoverflow
Solution 11 - JavaJin KwonView Answer on Stackoverflow
Solution 12 - JavaDuncan McGregorView Answer on Stackoverflow
Solution 13 - JavaTom Hawtin - tacklineView Answer on Stackoverflow
Solution 14 - JavacchabanoisView Answer on Stackoverflow
Solution 15 - JavaPavel NetesaView Answer on Stackoverflow
Solution 16 - Javasf298View Answer on Stackoverflow
Solution 17 - JavaRitam ChakrabortyView Answer on Stackoverflow