Как преобразовать список в int[] в Java?



это похоже на этот вопрос:
как конвертировать int[] в Integer[] в Java?



Я новичок в Java. Как я могу преобразовать List<Integer> to int[] в Java? Я в замешательстве, потому что List.toArray() на самом деле возвращает 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;
}


Я уверен, что есть лучший способ сделать это.

786   17  

17 ответов:

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

  • List<T>.toArray не будет работать, потому что нет никакого преобразования из Integer to int
  • вы не можете использовать int в качестве аргумента типа для дженериков, так что это будет есть быть int - конкретный метод (или тот, который использовал отражение, чтобы сделать неприятный обман.)

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

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

еще никто не упоминал потоки, добавленные в Java 8, так что вот оно:

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

мысли:

  • простой Stream#toArray возвращает Object[], Так что это не то, что мы хотим. Также Stream#toArray(IntFunction<A[]> generator) не делает то, что мы хотим, потому что общий тип A не может представлять примитив int
  • поэтому было бы неплохо иметь некоторый поток, который мог бы обрабатывать примитивный тип int, потому что toArray метод, скорее всего, также вернет int[] массив (возвращая что-то еще вроде Object[] или даже в штучной упаковке Integer[] было бы противоестественно, здесь). И к счастью Java 8 имеет такой поток:IntStream
  • так что теперь единственное, что нам нужно выяснить, это как преобразовать наш Stream<Integer> (который будет возвращен из list.stream()) к этому блестящему IntStream. Здесь mapToInt метод приходит на помощь. Все, что нам нужно сделать, это предоставить некоторое отображение из Integer до int. Мы могли бы использовать что-то вроде Integer#getValue который возвращает int:

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

    (или если кто-то предпочитает mapToInt(Integer::intValue))

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

    так что мы можем просто написать

    mapToInt((Integer i)->i)

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

    mapToInt(i -> i)

в дополнение к Commons Lang, вы можете сделать это с гуавы ' s метод Ints.toArray(Collection<Integer> collection):

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

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

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

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));
int[] toIntArray(List<Integer> list)  {
    int[] ret = new int[list.size()];
    int i = 0;
    for (Integer e : list)  
        ret[i++] = e;
    return ret;
}

небольшое изменение кода, чтобы избежать дорогостоящего индексирования списка (поскольку список не обязательно является ArrayList, но может быть связанным списком, для которого случайный доступ дорог)

Java 8 дал нам простой способ сделать это с помощью потоков...

использование коллекций stream() функция, а затем сопоставление с ints, вы получите IntStream. С помощью IntStream мы можем вызвать toArray () который дает нам int []

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

to int []

в IntStream

здесь Java 8 однострочный код для этого

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

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

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

Если Java разрешила несколько объявлений в цикле for, как это делает C++, мы могли бы пойти еще дальше и сделать for(int i = 0, Iterator it...

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

этот простой цикл всегда правильный! нет ошибок

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

если вы просто сопоставление Integer до int затем вы должны рассмотреть используя параллелизм, так как ваша логика отображения не зависит от каких-либо переменных за пределами своей области.

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

просто знайте об этом

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


существует два способа отображения целых чисел в их примитивную форму:

  1. через a ToIntFunction.

    mapToInt(Integer::intValue)
    
  2. через явные анбоксинг С лямбда-выражение.

    mapToInt(i -> i.intValue())
    
  3. через неявную (авто-) распаковку с лямбда выражение.

    mapToInt(i -> i)
    

учитывая список с null стоимостью

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

вот три варианта обработки null:

  1. на null значения перед отображением.
    int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
    
  2. карта null значения по умолчанию.

    int[] arr = list.parallelStream().map(i -> i == null ? -1 : i).mapToInt(Integer::intValue).toArray();
    
  3. дескриптор null внутри лямбда-выражения.

    int[] arr = list.parallelStream().mapToInt(i -> i == null ? -1 : i.intValue()).toArray();
    
int[] ret = new int[list.size()];       
Iterator<Integer> iter = list.iterator();
for (int i=0; iter.hasNext(); i++) {       
    ret[i] = iter.next();                
}                                        
return ret;                              

на самом деле нет способа "однострочного" того, что вы пытаетесь сделать, потому что toArray возвращает объект [], и вы не можете бросить из объекта[] в int[] или Integer[] в int[]

попробуйте доллар (Регистрация этой редакции):

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

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

С Коллекции Eclipse, вы можете сделать следующее, Если у вас есть список типа 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);

если у вас уже есть тип коллекций Eclipse, например MutableList, вы можете сделать следующее:

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

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

начиная с java 8 это может быть легко достигнуто с помощью Stream API

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

Если вы хотите получить дополнительную информацию о том, как этот процесс завершен id хотел бы перенаправить вас по этой ссылке http://www.techiedelight.com/convert-stream-array-java/#2

Я бы рекомендовал вам использовать List<?> скелетная реализация из API коллекций java, похоже, очень полезна в этом конкретном случае:

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

остерегайтесь бокса / распаковки недостатков

используя лямбду, вы можете сделать это (компилируется в 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);
    }

Comments

    Ничего не найдено.