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

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

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

Ответ 1

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

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

Ответ 2

Если вы используете java-8 там также еще один способ сделать это.

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

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

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

Вы также можете явно вызвать intValue с помощью ссылки на метод, т.е.

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]

Ответ 3

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

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

Ответ 4

Google Guava

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

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

Ответ 5

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

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

Ответ 6

с помощью Dollar должно быть довольно просто:

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

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

Ответ 7

Если вы используете Eclipse Collections, вы можете использовать метод 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.

Ответ 8

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

Просто пойдите с Apache Commons

Ответ 9

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

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

Не слишком фантазия; но, эй, это работает...

Ответ 10

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

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

Стоит отметить, что ArrayList должен быть объявлен так:

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

Ответ 11

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

Ответ 12

передать Arraylist или список целых чисел.

private int [] ArrayListIntoArrayConversion (List<Integer> list) {
    int[] array = new int[list.size()];
    Iterator<Integer> iterator = list.iterator();
    for (int i:list) {
        array[i] = iterator.next();
    }
    return array;
}

Ответ 13

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

Ответ 14

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

Доступ arr как обычный int[].