Home » Java » How to convert List<Integer> to int[] in Java?

How to convert List<Integer> to int[] in Java?

Posted by: admin November 2, 2017 Leave a comment

Questions:

This is similar to this question:
How to convert int[] to Integer[] in Java?

I’m new to Java. How can i convert a List<Integer> to int[] in Java? I’m confused because List.toArray() actually returns an Object[], which can be cast to nether Integer[] or int[].

Right now I’m using a loop to do so:

int[] toIntArray(List<Integer> list){
  int[] ret = new int[list.size()];
  for(int i = 0;i < ret.length;i++)
    ret[i] = list.get(i);
  return ret;
}

I’m sure there’s a better way to do this.

Answers:

Unfortunately, I don’t believe there really is a better way of doing this due to the nature of Java’s handling of primitive types, boxing, arrays and generics. In particular:

  • List<T>.toArray won’t work because there’s no conversion from Integer to int
  • You can’t use int as a type argument for generics, so it would have to be an int-specific method (or one which used reflection to do nasty trickery).

I believe there are libraries which have autogenerated versions of this kind of method for all the primitive types (i.e. there’s a template which is copied for each type). It’s ugly, but that’s the way it is I’m afraid 🙁

Even though the Arrays class came out before generics arrived in Java, it would still have to include all the horrible overloads if it were introduced today (assuming you want to use primitive arrays).

Questions:
Answers:

No one mentioned yet streams added in Java 8 so here it goes:

int[] array = list.stream().mapToInt(i->i).toArray();

Thought process:

  • simple Stream#toArray returns Object[], so it is not what we want. Also Stream#toArray(IntFunction<A[]> generator) doesn’t do what we want because generic type A can’t represent primitive int
  • so it would be nice to have some stream which could handle primitive type int, because its toArray method will most probably also return int[] array (returning something else like Object[] or even boxed Integer[] would be unnatural here). And fortunately Java 8 has such stream: IntStream
  • so now only thing we need to figure out is how to convert our Stream<Integer> (which will be returned from list.stream()) to that shiny IntStream. Here mapToInt method comes to rescue. All we need to do is provide some mapping from Integer to int. We could use something like Integer#getValue which returns int:

    mapToInt( (Integer i) -> i.intValue())

    (or if someone prefers mapToInt(Integer::intValue) )

    but similar code can be generated using unboxing, since compiler knows that result of this lambda must be int (lambda in mapToInt is implementation of ToIntFunction interface which expects body for int applyAsInt(T value) method which is expected to return int).

    So we can simply write

    mapToInt((Integer i)->i)

    or simpler (since Integer i type can be inferred by compiler because List<Integer>#stream() returns Stream<Integer>)

    mapToInt(i -> i)

Questions:
Answers:

In addition to Commons Lang, you can do this with Guava‘s method Ints.toArray(Collection<Integer> collection):

List<Integer> list = ...
int[] ints = Ints.toArray(list);

This saves you having to do the intermediate array conversion that the Commons Lang equivalent requires yourself.

Questions:
Answers:

The easiest way to do this is to make use of Apache Commons Lang. It has a handy ArrayUtils class that can do what you want. Use the toPrimitive method with the overload for an array of Integers.

List<Integer> myList;
 ... assign and fill the list
int[] intArray = ArrayUtils.toPrimitive(myList.toArray(new Integer[myList.size()]));

This way you don’t reinvent the wheel. Commons Lang has a great many useful things that Java left out. Above, I chose to create an Integer list of the right size. You can also use a 0-length static Integer array and let Java allocate an array of the right size:

static final Integer[] NO_INTS = new Integer[0];
   ....
int[] intArray2 = ArrayUtils.toPrimitive(myList.toArray(NO_INTS));

Questions:
Answers:
int[] toIntArray(List<Integer> list)  {
    int[] ret = new int[list.size()];
    int i = 0;
    for (Integer e : list)  
        ret[i++] = e.intValue();
    return ret;
}

Slight change to your code to avoid expensive list indexing (since a List is not necessarily an ArrayList, but could be a linked list, for which random access is expensive)

Questions:
Answers:

Here is Java 8 single line code for this

public int[] toIntArray(List<Integer> intList){
       return intList.stream().mapToInt(Integer::intValue).toArray();
}

Questions:
Answers:

Java 8 has given us a easy way to do this via streams…

Using the collections stream() function and then mapping to ints, you’ll get an IntStream. With the IntStream we can call toArray() which gives us int []

int [] ints = list.stream().mapToInt(Integer::intValue).toArray();

to int []

to IntStream

Questions:
Answers:

I’ll throw one more in here. I’ve noticed several uses of for loops, but you don’t even need anything inside the loop. I mention this only because the original question was trying to find less verbose code.

int[] toArray(List<Integer> list) {
    int[] ret = new int[ list.size() ];
    int i = 0;
    for( Iterator<Integer> it = list.iterator(); 
         it.hasNext(); 
         ret[i++] = it.next() );
    return ret;
}

If Java allowed multiple declarations in a for loop the way C++ does, we could go a step further and do for(int i = 0, Iterator it…

In the end though (this part is just my opinion), if you are going to have a helping function or method to do something for you, just set it up and forget about it. It can be a one-liner or ten; if you’ll never look at it again you won’t know the difference.

Questions:
Answers:

This simple loop is always correct! no bugs

  int[] integers = new int[myList.size()];
  for (int i = 0; i < integers.length; i++) {
      integers[i] = myList.get(i);
  }

Questions:
Answers:
int[] ret = new int[list.size()];       
Iterator<Integer> iter = list.iterator();
for (int i=0; iter.hasNext(); i++) {       
    ret[i] = iter.next();                
}                                        
return ret;                              

Questions:
Answers:

If you are simply mapping an Integer to an int then you should consider using parallelism, since your mapping logic does not rely on any variables outside its scope.

int[] arr = list.parallelStream().mapToInt(Integer::intValue).toArray();

Just be aware of this

Note that parallelism is not automatically faster than performing operations serially, although it can be if you have enough data and processor cores. While aggregate operations enable you to more easily implement parallelism, it is still your responsibility to determine if your application is suitable for parallelism.


There are two ways to map Integers to their primitive form:

  1. Via a ToIntFunction.

    mapToInt(Integer::intValue)
    
  2. Via explicit unboxing with lambda expression.

    mapToInt(i -> i.intValue())
    
  3. Via implicit (auto-) unboxing with lambda expression.

    mapToInt(i -> i)
    

Given a list with a null value

List<Integer> list = Arrays.asList(1, 2, null, 4, 5);

Here are three options to handle null:

  1. Filter out the null values before mapping.

    int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
    
  2. Map the null values to a default value.

    int[] arr = list.parallelStream().map(i -> i == null ? -1 : i).mapToInt(Integer::intValue).toArray();
    
  3. Handle null inside the lambda expression.

    int[] arr = list.parallelStream().mapToInt(i -> i == null ? -1 : i.intValue()).toArray();
    
Questions:
Answers:

There is really no way of “one-lining” what you are trying to do because toArray returns an Object[] and you cannot cast from Object[] to int[] or Integer[] to int[]

Questions:
Answers:

try also Dollar (check this revision):

import static com.humaorie.dollar.Dollar.*
...

List<Integer> source = ...;
int[] ints = $(source).convert().toIntArray();

Questions:
Answers:

Using a lambda you could do this (compiles in jdk lambda):

public static void main(String ars[]) {
        TransformService transformService = (inputs) -> {
            int[] ints = new int[inputs.size()];
            int i = 0;
            for (Integer element : inputs) {
                ints[ i++ ] = element;
            }
            return ints;
        };

        List<Integer> inputs = new ArrayList<Integer>(5) { {add(10); add(10);} };

        int[] results = transformService.transform(inputs);
    }

    public interface TransformService {
        int[] transform(List<Integer> inputs);
    }

Questions:
Answers:

I would recommend you to use List<?> skeletal implementation from the java collections API, it appears to be quite helpful in this particular case:

package mypackage;

import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Test {

//Helper method to convert int arrays into Lists
static List<Integer> intArrayAsList(final int[] a) {
    if(a == null)
        throw new NullPointerException();
    return new AbstractList<Integer>() {

        @Override
        public Integer get(int i) {
            return a[i];//autoboxing
        }
        @Override
        public Integer set(int i, Integer val) {
            final int old = a[i];
            a[i] = val;//auto-unboxing
            return old;//autoboxing
        }
        @Override
        public int size() {
            return a.length;
        }
    };
}

public static void main(final String[] args) {
    int[] a = {1, 2, 3, 4, 5};
    Collections.reverse(intArrayAsList(a));
    System.out.println(Arrays.toString(a));
}
}

Beware of boxing/unboxing drawbacks

Questions:
Answers:

With Eclipse Collections, you can do the following if you have a list of type java.util.List<Integer>:

List<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5);
int[] ints = LazyIterate.adapt(integers).collectInt(i -> i).toArray();

Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, ints);

If you already have an Eclipse Collections type like MutableList, you can do the following:

MutableList<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5);
int[] ints = integers.asLazy().collectInt(i -> i).toArray();

Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, ints);

Note: I am a committer for Eclipse Collections

Questions:
Answers:
@Override
public int findArray(int[] array, int[] subArray) {

    Map<Integer, Integer> map = new LinkedHashMap();
    int index = -1;
    boolean flag = false;
    for (int i = 0; i < subArray.length; i++) {
        flag=false;
        for (int j = 0; j < array.length; j++) {
            if (subArray[i]==array[j]) {
                map.put(subArray[i], j);
                flag = true;
            }   
        }
    }
    if (flag) {
        Map.Entry<Integer, Integer> entry = map.entrySet().iterator().next();
        index = entry.getValue();
    }

    return index;
}