Вопрос-ответ

How can I convert List to int[] in Java? [duplicate]

Как я могу преобразовать List в int[] в Java?

Как я могу преобразовать List<Integer> в int[] в Java?

Я в замешательстве, потому что List.toArray() на самом деле возвращает an Object[], который не может быть преобразован ни в Integer[], ни int[].

Прямо сейчас я использую цикл для этого:

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

Есть ли лучший способ сделать это?

Это похоже на вопрос Как я могу преобразовать int[] в Integer[] в Java?.

Переведено автоматически
Ответ 1

С потоками, добавленными в Java 8, мы можем написать код типа:

int[] example1 = list.stream().mapToInt(i->i).toArray();
// OR
int[] example2 = list.stream().mapToInt(Integer::intValue).toArray();

Мыслительный процесс:


  • Простой Stream#toArray возвращает Object[] массив, так что это не то, что мы хотим. Кроме того, Stream#toArray(IntFunction<A[]> generator) который возвращает A[], не делает того, что мы хотим, потому что универсальный тип A не может представлять примитивный тип int



  • Итак, было бы неплохо иметь какой-то поток, который был бы разработан для обработки примитивного типа int вместо ссылочного типа like Integer, потому что его toArray метод, скорее всего, также вернет int[] массив (возвращать что-то другое, например, Object[] или даже в штучной упаковке Integer[] было бы неестественно для int). И, к счастью, в Java 8 есть такой поток, который IntStream



  • Итак, теперь единственное, что нам нужно выяснить, это как преобразовать наш Stream<Integer> (который будет возвращен из list.stream()) в этот блестящий IntStream.


    Быстрый поиск в документации по Stream при поиске методов, которые возвращают IntStream указывает нам на наше решение, которое является mapToInt(ToIntFunction<? super T> mapper) методом. Все, что нам нужно сделать, это предоставить отображение из Integer в int.


    Поскольку ToIntFunction это функциональный интерфейс, мы также можем предоставить его экземпляр через lambda или ссылку на метод.


    В любом случае, чтобы преобразовать Integer в int, мы можем использовать Integer#intValue so внутри mapToInt мы можем написать:


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

    (или некоторые могут предпочесть: mapToInt(Integer::intValue).)


    Но аналогичный код может быть сгенерирован с помощью распаковки, поскольку компилятор знает, что результат этого лямбда-выражения должен иметь тип int (лямбда, используемая в mapToInt, является реализацией ToIntFunction интерфейса, который ожидает в качестве тела метод типа: int applyAsInt(T value) который, как ожидается, вернет int).


    Итак, мы можем просто написать:


    mapToInt((Integer i)->i)

    Кроме того, поскольку Integer тип в (Integer i) может быть определен компилятором, потому что List<Integer>#stream() возвращает a Stream<Integer>, мы также можем пропустить его, что оставляет нас с


    mapToInt(i -> i)


Ответ 2

К сожалению, я не верю, что на самом деле есть лучший способ сделать это из-за особенностей обработки Java примитивных типов, боксов, массивов и обобщений. В частности.:


  • List<T>.toArray не будет работать, потому что нет преобразования из Integer в int

  • Вы не можете использовать int в качестве аргумента типа для generics, поэтому это должен быть int специфичный метод (или тот, который использовал отражение для выполнения неприятных трюков).

Я полагаю, что существуют библиотеки, которые имеют автоматически созданные версии такого метода для всех примитивных типов (т. Е. Есть шаблон, который копируется для каждого типа). Это некрасиво, но, боюсь, так оно и есть :(

Несмотря на то, что Arrays класс появился до появления generics в Java, ему все равно пришлось бы включать все ужасные перегрузки, если бы он был представлен сегодня (при условии, что вы хотите использовать примитивные массивы).

Ответ 3

В дополнение к Commons Lang, вы можете сделать это с помощью метода Guava Ints.toArray(Collection<Integer> collection):

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

Это избавляет вас от необходимости самостоятельно выполнять промежуточное преобразование массива, которое требуется для эквивалента Commons Lang.

Ответ 4

Самый простой способ сделать это - использовать Apache Commons Lang. У него есть удобный класс ArrayUtils, который может делать то, что вы хотите. Используйте toPrimitive метод с перегрузкой для массива Integers.

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

Таким образом, вы не изобретаете велосипед заново. В Commons Lang есть множество полезных вещей, которые Java упустила. Выше я решил создать список целых чисел нужного размера. Вы также можете использовать статический целочисленный массив длиной 0 и позволить Java выделить массив нужного размера:

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