Como converter List para int em Java?

Isso é semelhante a esta pergunta: Como converter int [] para Integer [] em Java?

Eu sou novo em Java. Como posso converter uma List para int[] em Java? Estou confuso porque List.toArray() na verdade, retorna um Object[] , que pode ser convertido em Integer[] ou int[] .

Neste momento estou usando um loop para fazer isso:

 int[] toIntArray(List list){ int[] ret = new int[list.size()]; for(int i = 0;i < ret.length;i++) ret[i] = list.get(i); return ret; } 

Tenho certeza de que há uma maneira melhor de fazer isso.

Infelizmente, não acredito que exista uma maneira melhor de fazer isso devido à natureza da manipulação de tipos primitivos, boxe, matrizes e genéricos do Java. Em particular:

  • List.toArray não funcionará porque não há conversão de Integer para int
  • Você não pode usar int como um argumento de tipo para genéricos, então teria que ser um método específico de int (ou um que usasse reflection para fazer truques desagradáveis).

Acredito que existam bibliotecas que possuem versões autogeradas desse tipo de método para todos os tipos primitivos (ou seja, há um modelo que é copiado para cada tipo). É feio, mas é assim que eu tenho medo 🙁

Mesmo que a class Arrays tenha saído antes dos genéricos chegarem em Java, ela ainda teria que include todas as sobrecargas horríveis se fosse introduzida hoje (supondo que você queira usar matrizes primitivas).

Ninguém mencionou ainda streams adicionados no Java 8, então aqui vai:

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

Processo de pensamento:

  • Stream#toArray simples Stream#toArray retorna Object[] , então não é o que queremos. Também o Stream#toArray(IntFunction generator) não faz o que queremos porque o tipo genérico A não pode representar int primitivo
  • então seria legal ter algum stream que pudesse manipular o tipo primitivo int , porque seu método toArray muito provavelmente retornará int[] array (retornando algo como Object[] ou mesmo Integer[] seria anormal aqui). E, felizmente, o Java 8 tem esse stream: IntStream
  • Então, agora, a única coisa que precisamos descobrir é como converter nosso Stream (que será retornado de list.stream() ) para esse IntStream shiny. Aqui mapToInt método vem para resgatar. Tudo o que precisamos fazer é fornecer algum mapeamento de Integer para int . Poderíamos usar algo como Integer#getValue que retorna int :

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

    (ou se alguém prefere mapToInt(Integer::intValue) )

    mas código semelhante pode ser gerado usando unboxing, já que o compilador sabe que o resultado desse lambda deve ser int (lambda em mapToInt é a implementação da interface ToIntFunction que espera corpo para o int applyAsInt(T value) que deve retornar int ).

    Então nós podemos simplesmente escrever

    mapToInt((Integer i)->i)

    ou mais simples (já Integer i tipo Integer i pode ser inferido pelo compilador porque List#stream() retorna Stream )

    mapToInt(i -> i)

Além do Commons Lang, você pode fazer isso com o método de Guava Ints.toArray(Collection collection) :

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

Isso evita que você tenha que fazer a conversão de matriz intermediária que o equivalente do Commons Lang requer.

A maneira mais fácil de fazer isso é fazer uso do Apache Commons Lang . Tem uma class de ArrayUtils acessível que pode fazer o que você quer. Use o método toPrimitive com a sobrecarga para uma matriz de Integer s.

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

Desta forma, você não reinventa a roda. O Commons Lang tem muitas coisas úteis que o Java deixou de fora. Acima, optei por criar uma lista Integer do tamanho certo. Você também pode usar uma matriz Integer estática de 0 comprimento e permitir que o Java aloque uma matriz do tamanho correto:

 static final Integer[] NO_INTS = new Integer[0]; .... int[] intArray2 = ArrayUtils.toPrimitive(myList.toArray(NO_INTS)); 
 int[] toIntArray(List list) { int[] ret = new int[list.size()]; int i = 0; for (Integer e : list) ret[i++] = e; return ret; } 

Ligeira alteração no seu código para evitar indexação de lista cara (já que uma lista não é necessariamente uma ArrayList, mas pode ser uma linked list, para a qual o access random é caro)

O Java 8 nos deu uma maneira fácil de fazer isso através de streams …

Usando a function stream() collections e depois mapeando para ints, você obterá um IntStream. Com o IntStream podemos chamar o toArray () que nos dá int []

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

para int []

para o IntStream

Aqui está o código de linha única Java 8 para este

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

Vou jogar mais um aqui. Eu notei vários usos de loops for, mas você nem precisa de nada dentro do loop. Eu menciono isso apenas porque a pergunta original estava tentando encontrar um código menos detalhado.

 int[] toArray(List list) { int[] ret = new int[ list.size() ]; int i = 0; for( Iterator it = list.iterator(); it.hasNext(); ret[i++] = it.next() ); return ret; } 

Se o Java permitisse várias declarações em um loop for como o C ++ faz, nós poderíamos dar um passo adiante e fazer por (int i = 0, Iterator it …

No final das contas (esta parte é apenas a minha opinião), se você vai ter uma function ou método de ajuda para fazer algo para você, basta configurá-lo e esquecê-lo. Pode ser um one-liner ou dez; se você nunca mais olhar para ele, não saberá a diferença.

Esse loop simples está sempre correto! sem bugs

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

Se você está simplesmente mapeando um Integer para um int então deve considerar o uso do paralelismo , já que sua lógica de mapeamento não depende de nenhuma variável fora de seu escopo.

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

Apenas esteja ciente disso

Observe que o paralelismo não é automaticamente mais rápido do que executar operações em série, embora possa ser se você tiver dados e núcleos de processador suficientes. Embora as operações agregadas permitam que você implemente o paralelismo com mais facilidade, ainda é sua responsabilidade determinar se o aplicativo é adequado para paralelismo.


Existem duas maneiras de mapear Inteiros para sua forma primitiva:

  1. Através de um ToIntFunction .

     mapToInt(Integer::intValue) 
  2. Via unboxing explícito com expressão lambda.

     mapToInt(i -> i.intValue()) 
  3. Via descompression (auto) implícita com expressão lambda.

     mapToInt(i -> i) 

Dada uma lista com um valor null

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

Aqui estão três opções para manipular null :

  1. Filtre os valores null antes do mapeamento.

     int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray(); 
  2. Mapeie os valores null para um valor padrão.

     int[] arr = list.parallelStream().map(i -> i == null ? -1 : i).mapToInt(Integer::intValue).toArray(); 
  3. Manipular null dentro da expressão lambda.

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

Não há realmente nenhuma maneira de “um-lining” o que você está tentando fazer porque toArray retorna um Object [] e você não pode converter de Object [] para int [] ou Integer [] para int []

tente também Dollar ( confira esta revisão ):

 import static com.humaorie.dollar.Dollar.* ... List source = ...; int[] ints = $(source).convert().toIntArray(); 

Com Coleções do Eclipse , você pode fazer o seguinte se tiver uma lista do tipo java.util.List :

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

Se você já tiver um tipo Coleções do Eclipse como MutableList , poderá fazer o seguinte:

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

Nota: Eu sou um committer para collections do Eclipse

Eu recomendo que você use a implementação esquelética List< ?> API de collections java, parece ser bastante útil neste caso em particular:

 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 intArrayAsList(final int[] a) { if(a == null) throw new NullPointerException(); return new AbstractList() { @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)); } } 

Cuidado com as desvantagens do boxe / unboxing

Começando com o java 8, isso pode ser facilmente alcançado usando a Stream API

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

Se você gostaria de ter mais informações sobre como este processo é concluído, gostaria de redirecioná-lo para este link http://www.techiedelight.com/convert-stream-array-java/#2

Usando um lambda você poderia fazer isso (compila em 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 inputs = new ArrayList(5) { {add(10); add(10);} }; int[] results = transformService.transform(inputs); } public interface TransformService { int[] transform(List inputs); }