¿Cómo puedo convertir List<Integer> a int[] en Java? [duplicar]
¿Cómo puedo convertir un List<Integer>
aint[]
Java?
Estoy confundido porque List.toArray()
en realidad devuelve un Object[]
, que no se puede convertir ni Integer[]
a niint[]
.
Ahora mismo estoy usando un bucle para hacerlo:
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;
}
¿Existe una mejor manera de hacer esto?
Esto es similar a la pregunta ¿Cómo puedo convertir int[] a Integer[] en Java? .
Con las secuencias agregadas en Java 8 podemos escribir código como:
int[] example1 = list.stream().mapToInt(i->i).toArray();
// OR
int[] example2 = list.stream().mapToInt(Integer::intValue).toArray();
Proceso de pensamiento:
El simple
Stream#toArray
devuelve unaObject[]
matriz, por lo que no es lo que queremos. Además,Stream#toArray(IntFunction<A[]> generator)
lo que devuelveA[]
no hace lo que queremos, porque el tipo genéricoA
no puede representar el tipo primitivo.int
Por lo tanto, sería bueno tener algún tipo de flujo que estuviera diseñado para manejar tipos primitivos
int
en lugar del tipo de referencia comoInteger
, porquetoArray
lo más probable es que su método también devuelva unaint[]
matriz (devolver algo más comoObject[]
o incluso en un cuadroInteger[]
no sería natural paraint
). Y afortunadamente Java 8 tiene esa corriente que esIntStream
Así que ahora lo único que tenemos que descubrir es cómo convertir nuestro
Stream<Integer>
(que será devueltolist.stream()
) a ese shinyIntStream
.La búsqueda rápida en la documentación
Stream
mientras buscamos métodos que regresenIntStream
nos dirige a nuestra solución, que esmapToInt(ToIntFunction<? super T> mapper)
el método. Todo lo que necesitamos hacer es proporcionar un mapeo desdeInteger
hastaint
.Dado que
ToIntFunction
es una interfaz funcional, también podemos proporcionar su instancia mediante lambda o referencia de método .De todos modos, para convertir Integer a int podemos usar,
Integer#intValue
por lo que dentromapToInt
podemos escribir:mapToInt( (Integer i) -> i.intValue() )
(o algunos tal vez prefieran:
mapToInt(Integer::intValue)
.)Pero se puede generar un código similar usando unboxing, ya que el compilador sabe que el resultado de esta lambda debe ser de tipo
int
(la lambda utilizadamapToInt
es una implementación de laToIntFunction
interfaz que espera como cuerpo un método de tipo:int applyAsInt(T value)
que se espera que devuelva unint
) .Entonces podemos simplemente escribir:
mapToInt((Integer i)->i)
Además, dado que el compilador puede inferir el
Integer
tipo in porque devuelve a , también podemos omitirlo, lo que nos deja con(Integer i)
List<Integer>#stream()
Stream<Integer>
mapToInt(i -> i)
Desafortunadamente, no creo que realmente exista una mejor manera de hacer esto debido a la naturaleza del manejo que hace Java de tipos primitivos, boxeo, matrices y genéricos. En particular:
List<T>.toArray
no funcionará porque no hay conversión deInteger
aint
- No se puede usar
int
como argumento de tipo para genéricos, por lo que tendría que ser unint
método específico (o uno que usara 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 me temo que así es :(
Aunque la Arrays
clase apareció antes de que llegaran los genéricos a Java, aún tendría que incluir todas las horribles sobrecargas si se introdujera hoy (suponiendo que desee utilizar matrices primitivas).