¿Cómo convertir List a int en Java?

Esto es similar a esta pregunta: ¿Cómo convertir int [] a Integer [] en Java?

Soy nuevo en Java. ¿Cómo puedo convertir una List a int[] en Java? Estoy confundido porque List.toArray() realidad devuelve un Object[] , que puede enviarse a Nether Integer[] o int[] .

En este momento estoy usando un loop para hacerlo:

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

Estoy seguro de que hay una mejor manera de hacer esto.

Desafortunadamente, no creo que haya una forma mejor de hacerlo debido a la naturaleza del manejo de Java de tipos primitivos, boxeo, matrices y generics. En particular:

  • List.toArray no funcionará porque no hay conversión de Integer a int
  • No se puede usar int como un argumento de tipo para generics, por lo que tendría que ser un método específico de int (o uno que utilizara la reflexión para hacer trucos desagradables).

Creo que hay bibliotecas que tienen versiones autogeneradas de este tipo de método para todos los tipos primitivos (es decir, hay una plantilla que se copia para cada tipo). Es feo, pero así es como me temo 🙁

A pesar de que la clase Arrays salió antes de que los generics llegaran a Java, aún tendría que incluir todas las sobrecargas horribles si se introdujera hoy (suponiendo que quiera usar matrices primitivas).

Nadie mencionó aún las secuencias agregadas en Java 8, así que aquí va:

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

Proceso de pensamiento:

  • simple Stream#toArray devuelve Object[] , por lo que no es lo que queremos. También Stream#toArray(IntFunction generator) no hace lo que queremos porque el tipo genérico A no puede representar primitive int
  • así que sería bueno tener algún flujo que pudiera manejar el tipo primitivo int , porque su método toArray probablemente también devolverá int[] array (devolver algo más como Object[] o incluso el Integer[] caja Integer[] no sería natural aquí). Y afortunadamente Java 8 tiene tal flujo: IntStream
  • así que ahora lo único que tenemos que averiguar es cómo convertir nuestro Stream (que se devolverá de list.stream() ) a ese IntStream shiny. Aquí el método mapToInt viene a rescatar. Todo lo que tenemos que hacer es proporcionar alguna asignación de Integer a int . Podríamos usar algo como Integer#getValue que devuelve int :

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

    (o si alguien prefiere mapToInt(Integer::intValue) )

    pero se puede generar un código similar usando unboxing, ya que el comstackdor sabe que el resultado de esta lambda debe ser int (lambda en mapToInt es la implementación de la interfaz ToIntFunction que espera cuerpo para el int applyAsInt(T value) que se espera que devuelva int ).

    Entonces, simplemente podemos escribir

    mapToInt((Integer i)->i)

    o más simple (dado que el comstackdor puede inferir el tipo Integer i porque List#stream() devuelve Stream )

    mapToInt(i -> i)

Además de Commons Lang, puedes hacer esto con el método de Guava Ints.toArray(Collection collection) :

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

Esto le ahorra tener que hacer la conversión de matriz intermedia que requiere el equivalente de Commons Lang.

La forma más fácil de hacerlo es hacer uso de Apache Commons Lang . Tiene una práctica clase ArrayUtils que puede hacer lo que quieras. Utilice el método toPrimitive con la sobrecarga para una matriz de Integer .

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

De esta manera no reinventas la rueda. Commons Lang tiene muchas cosas útiles que Java omitió. Arriba, elegí crear una lista entera del tamaño correcto. También puede usar una matriz de enteros estáticos de 0 longitudes y dejar que Java asigne una matriz del tamaño correcto:

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

Leve cambio a su código para evitar la indexación costosa de la lista (ya que una Lista no es necesariamente una Lista de Arreglos, pero podría ser una lista vinculada, para la cual el acceso aleatorio es costoso)

Java 8 nos ha brindado una manera fácil de hacerlo a través de transmisiones …

Usando la función de recostackción de stream() y luego mapeando a las entradas, obtendrá un IntStream. Con IntStream podemos llamar a Array () que nos da int []

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

a int []

a IntStream

Aquí está el código de una sola línea de Java 8 para esto

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

Lanzaré uno más aquí. Me he dado cuenta de varios usos de los bucles for, pero ni siquiera necesitas nada dentro del bucle. Menciono esto solo porque la pregunta original intentaba encontrar un código menos detallado.

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

Si Java permitiera múltiples declaraciones en un bucle for del modo en que lo hace C ++, podríamos ir un paso más allá y hacer por (int i = 0, Iterator it …

Aunque al final (esta parte es solo mi opinión), si vas a tener una función o método de ayuda para hacer algo por ti, simplemente configúralo y olvídate de él. Puede ser un trazador de líneas o diez; si nunca lo vuelves a mirar, no sabrás la diferencia.

¡Este simple bucle es siempre correcto! no hay errores

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

Si simplemente está mapeando un Integer a un int entonces debería considerar el uso de paralelismo , ya que su lógica de mapeo no se basa en ninguna variable fuera de su scope.

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

Solo se consciente de esto

Tenga en cuenta que el paralelismo no es automáticamente más rápido que realizar operaciones en serie, aunque puede ser si tiene suficientes datos y núcleos de procesador. Si bien las operaciones agregadas le permiten implementar el paralelismo de manera más fácil, sigue siendo su responsabilidad determinar si su aplicación es adecuada para el paralelismo.


Hay dos formas de asignar enteros a su forma primitiva:

  1. A través de una función ToIntFunction .

     mapToInt(Integer::intValue) 
  2. A través de unboxing explícito con expresión lambda.

     mapToInt(i -> i.intValue()) 
  3. Vía implícita (auto) unboxing con expresión lambda.

     mapToInt(i -> i) 

Dada una lista con un valor null

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

Aquí hay tres opciones para manejar null :

  1. Filtra los valores null antes del mapeo.

     int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray(); 
  2. Asigne los valores null a un valor predeterminado.

     int[] arr = list.parallelStream().map(i -> i == null ? -1 : i).mapToInt(Integer::intValue).toArray(); 
  3. Manejar null dentro de la expresión 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; 

Realmente no hay forma de “alinear” lo que estás tratando de hacer porque toArray devuelve un Object [] y no puedes convertir desde Object [] a int [] o Integer [] a int []

prueba también Dollar ( mira esta revisión ):

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

Con Eclipse Collections , puede hacer lo siguiente si tiene una lista de 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); 

Si ya tiene un tipo de colecciones de Eclipse como MutableList , puede hacer lo siguiente:

 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: soy un committer para las colecciones de Eclipse

Te recomendaría usar la implementación esquemática de List< ?> De la API de colecciones java, parece ser bastante útil en este caso 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 con los inconvenientes del boxeo / desempaquetado

Comenzando con java 8 esto se puede lograr fácilmente usando Stream API

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

si desea obtener más información sobre cómo se completa este proceso, id como redirigirlo a este enlace http://www.techiedelight.com/convert-stream-array-java/#2

Usando una lambda puedes hacer esto (comstack en 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); }