Как преобразовать ArrayList, содержащий целые числа, в примитивный массив int?

Я пытаюсь преобразовать ArrayList, содержащий целочисленные объекты, в примитивный int[] со следующим фрагментом кода, но он выдает ошибку времени компиляции. Можно ли конвертировать в Java?

List<Integer> x =  new ArrayList<Integer>();
int[] n = (int[])x.toArray(int[x.size()]);

12 ответов


вы можете конвертировать, но я не думаю, что есть что-то встроенное, чтобы сделать это автоматически:

public static int[] convertIntegers(List<Integer> integers)
{
    int[] ret = new int[integers.size()];
    for (int i=0; i < ret.length; i++)
    {
        ret[i] = integers.get(i).intValue();
    }
    return ret;
}

(обратите внимание, что это вызовет исключение NullPointerException, Если либо integers или любой элемент внутри него находится null.)

EDIT: согласно комментариям, вы можете использовать итератор списка, чтобы избежать неприятных затрат со списками, такими как LinkedList:

public static int[] convertIntegers(List<Integer> integers)
{
    int[] ret = new int[integers.size()];
    Iterator<Integer> iterator = integers.iterator();
    for (int i = 0; i < ret.length; i++)
    {
        ret[i] = iterator.next().intValue();
    }
    return ret;
}

если вы используете java-8 есть и другой способ сделать это.

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

что он делает:

  • получение Stream<Integer> из списка
  • получение IntStream путем сопоставления каждого элемента самому себе (функция идентификации), распаковка int значение удерживается каждым Integer объект (выполняется автоматически с Java 5)
  • получение массива int по телефону toArray

вы также может явного вызова intValue через ссылку на метод, i.e:

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

также стоит упомянуть, что вы можете получить NullPointerException если у вас есть какие-либо null ссылка в списке. Этого можно легко избежать, добавив условие фильтрации в конвейер потока следующим образом:

                       //.filter(Objects::nonNull) also works
int[] arr = list.stream().filter(i -> i != null).mapToInt(i -> i).toArray();

пример:

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

list.set(1, null); //[1, null, 3, 4]
arr = list.stream().filter(i -> i != null).mapToInt(i -> i).toArray(); //[1, 3, 4]

Apache Commons имеет класс ArrayUtils, который имеет метод toPrimitive (), который делает именно это.

import org.apache.commons.lang.ArrayUtils;
...
    List<Integer> list = new ArrayList<Integer>();
    list.add(new Integer(1));
    list.add(new Integer(2));
    int[] intArray = ArrayUtils.toPrimitive(list.toArray(new Integer[0]));

однако, как показал Джон, это довольно легко сделать самостоятельно вместо использования внешних библиотек.


Google Guava

Google Guava обеспечивает аккуратный способ сделать это путем вызова Ints.toArray.

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

Я считаю, что итерация с использованием итератора списка-лучшая идея, как list.get(i) может иметь низкую производительность в зависимости от реализации списка:

private int[] buildIntArray(List<Integer> integers) {
    int[] ints = new int[integers.size()];
    int i = 0;
    for (Integer n : integers) {
        ints[i++] = n;
    }
    return ints;
}

используя доллар должно быть довольно просто:

List<Integer> list = $(5).toList(); // the list 0, 1, 2, 3, 4  
int[] array = $($(list).toArray()).toIntArray();

Я планирую улучшить DSL, чтобы удалить промежуточное toArray() вызов


если вы используете Коллекции Eclipse можно использовать collectInt() метод переключения из контейнера объектов в примитивный контейнер int.

List<Integer> integers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
MutableIntList intList =
  ListAdapter.adapt(integers).collectInt(i -> i);
Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, intList.toArray());

если вы можете конвертировать ваши ArrayList до FastList, вы можете избавиться от переходника.

Assert.assertArrayEquals(
  new int[]{1, 2, 3, 4, 5},
  Lists.mutable.with(1, 2, 3, 4, 5)
    .collectInt(i -> i).toArray());

Примечание: Я коммиттер для коллекций Eclipse.


меня смущает, что мы поощряем одноразовые пользовательские методы, когда совершенно хорошая, хорошо используемая библиотека, такая как Apache Commons, уже решила проблему. Хотя решение тривиально, если не абсурдно, безответственно поощрять такое поведение из-за длительного обслуживания и доступности.

просто иди с Apache Commons


вы можете просто скопировать его в массив:

int[] arr = new int[list.size()];
for(int i = 0; i < list.size(); i++) {
    arr[i] = list.get(i);
}

Не слишком вычурно, но, эй, это работает...


этот фрагмент кода работает для меня, попробуйте это

Integer[] arr = x.toArray(new Integer[x.size()]);

   List<Integer> list = new ArrayList<Integer>();

    list.add(1);
    list.add(2);

    int[] result = null;
    StringBuffer strBuffer = new StringBuffer();
    for (Object o : list) {
        strBuffer.append(o);
        result = new int[] { Integer.parseInt(strBuffer.toString()) };
        for (Integer i : result) {
            System.out.println(i);
        }
        strBuffer.delete(0, strBuffer.length());
    }

Integer[] arr = (Integer[]) x.toArray(new Integer[x.size()]);

открыть arr вроде нормально int[].