21
  public static int[] convertListToArray(List<Integer> listResult) {
        int[] result = new int[listResult.size()];
        int i= 0;
        for (int num : listResult) {
            result[i++] = num;
        }
        return result;
    }

Is there an efficient way to convert List to array without iterating List explicitly ? Maybe it is possible by using methods like:

Arrays.copyOf(int [] origin , int newLength );
System.arraycopy(Object src,  int  srcPos,
                                    Object dest, int destPos,
                                    int length);

I know that there is a solution described here. However, I particularly interested in an efficient way of converting List<Integer> to int[]

Tim Florian
  • 408
  • 1
  • 3
  • 13
  • 1
    Possible duplicate of [Converting 'ArrayList to 'String\[\]' in Java](http://stackoverflow.com/questions/4042434/converting-arrayliststring-to-string-in-java) – Andrii Abramov Jan 07 '17 at 10:57
  • 3
    @AndriiAbramov: Except `String` is an object type and `int` is a primitive. `Integer[]` is not `int[]`. – T.J. Crowder Jan 07 '17 at 10:59
  • @ Tim - See my comment to Andrii above; is `int` significant here? If so, highlight it in the question, e.g. "List of Integers to a primitive int[]" – T.J. Crowder Jan 07 '17 at 11:01
  • @ Tim - Also: Why? What do you think will be inefficient about what you have? As there's a conversion required (`Integer` => `int`), you're not going to be able to offload this to a system call under the hood or similar... It might possibly be more efficient to use `toArray` to get an `Integer[]` and then do the loop, but also possibly not. You'd have to do a benchmark in your target code to see whether it was an improvement on what you have. – T.J. Crowder Jan 07 '17 at 11:03
  • are you using java 8 ? - you can use the java 8 stream i think – Anders Pedersen Jan 07 '17 at 11:06
  • yes. I use java 8. However, I'm more interesting in java 7 ( and below ) solutions. – Tim Florian Jan 07 '17 at 11:08
  • @T.J. Crowder. Thx for your attention. Yes, if you allow, I would like to highlight the problem restriction Integer[] => int[] – Tim Florian Jan 07 '17 at 11:11
  • There cannot be a technique that doesn't iterate, as `int[]` and `Integer[]` are not mutually coercible. – user207421 Jan 08 '17 at 02:31

4 Answers4

13

Given the need to convert from Integer to int, I don't think you're going to find something more efficient than what you have, if I assume you're talking about runtime efficiency.

You might find converting to Integer[] first and then looping might be more efficient (below), but you might not, too. You'd have to test it in your specific scenario and see.

Here's that example:

int size = listResult.size();
int[] result = new int[size];
Integer[] temp = listResult.toArray(new Integer[size]);
for (int n = 0; n < size; ++n) {
    result[n] = temp[n];
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
12

If efficiency is your primary concern, I think you can use your solution and make it more efficient by using an indexed for loop on the listResult if it is RandomAccess. However this makes the code much less readable, and you'd have to benchmark it for your use cases to see if it is more efficient.

public static int[] convertListToArray(List<Integer> listResult) {
    int size = listResult.size();
    int[] result = new int[size];
    if (listResult instanceof RandomAccess)
    {
        for (int i = 0; i < size; i++)
        {
            result[i] = listResult.get(i);
        }
    }
    else
    {
        int i = 0;
        for (int num : listResult) {
            result[i++] = num;
        }
    }
    return result;
}

If you use Java 8 and would like to write less code you can use the Streams library.

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int[] array = list.stream().mapToInt(i -> i).toArray();

If you are open to using a third party library, you can Eclipse Collections as follows.

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

The following is slightly more code, but is the most efficient solution I could come up with using Eclipse Collections.

MutableList<Integer> list = Lists.mutable.with(1, 2, 3, 4, 5);
int[] array = new int[list.size()];
list.forEachWithIndex((each, index) -> array[index] = each);

If you need to use the java.util.List interface, the ListIterate utility class can be used from Eclipse Collections.

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int[] array = new int[list.size()];
ListIterate.forEachWithIndex(list, (each, index) -> array[index] = each);

The ListIterate utility will use different iteration code for RandomAccess lists and non-RandomAccess lists.

The most efficient thing to do would be to change the List<Integer> to a MutableIntList in Eclipse Collections or another library that has support for primitive collections.

Note: I am a committer for Eclipse Collections.

Donald Raab
  • 6,458
  • 2
  • 36
  • 44
  • I have trouble seeing how the indexed for loop is more efficient than the enhanced for loop ? – Jean-François Savard Jan 08 '17 at 00:51
  • The enhanced for loop will create an Iterator. However, now that I think about it you make a fair point. If the List is a LinkedList, the indexed access approach would be much worse. This is one reason internal iterators on collections are preferable in my opinion. – Donald Raab Jan 08 '17 at 01:06
  • 2
    I updated the answer to handle both RandomAccess and non-RandomAccess Lists. There is no "guarantee" that the indexed access will be faster so benchmarking for the specific use cases would be the only way to show whether it is faster. https://docs.oracle.com/javase/8/docs/api/java/util/RandomAccess.html – Donald Raab Jan 08 '17 at 01:25
  • Would there be a way to do this more efficient if we know the `List` is an `ArrayList`? Would it be more efficient to convert the underlying array by `Arrays.stream(array).mapToInt(Integer::intValue).toArray();`? – Simon Baars May 15 '19 at 05:59
11

In Java 8:

int[] anArray = list.stream()
                    .filter(Objects::nonNull)
                    .mapToInt(Integer::intValue)
                    .toArray();
Saxintosh
  • 322
  • 2
  • 9
0

There is efficient way you could do this Java. However, this could open room for someone to create the generic function (depend on demand).

Just like this sample i wrote, I suggest you do the same to the specific knowledge of your program.

    // Generic function to convert set to list
    public static <T> ArrayList<T> convertSetToList(Set<T> set)
    {
        // create an empty list
        ArrayList<T> list = new ArrayList<>();
        // push each element in the set into the list
        for (T t : set)
            list.add(t);

        // return the list
        return list;
    }

olajide
  • 972
  • 1
  • 13
  • 26