objeto - ¿Cómo convertir la Lista<Integer> a int[] en Java?
object to int c# (17)
¡Este simple bucle siempre es correcto! sin errores
int[] integers = new int[myList.size()];
for (int i = 0; i < integers.length; i++) {
integers[i] = myList.get(i);
}
Esta pregunta ya tiene una respuesta aquí:
Esto es similar a esta pregunta: ¿Cómo convertir int [] a Integer [] en Java?
Soy nuevo en Java. ¿Cómo puedo convertir una List<Integer>
a int[]
en Java? Estoy confundido porque List.toArray()
realidad devuelve un Object[]
, que se puede convertir en Integer[]
inferior Integer[]
o int[]
.
En este momento 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;
}
Estoy seguro de que hay una mejor manera de hacer esto.
A partir de 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, puede redirigirlo a este enlace http://www.techiedelight.com/convert-stream-array-java/#2
Además de Commons Lang, puedes hacer esto con el método Ints.toArray(Collection<Integer> collection)
:
List<Integer> list = ...
int[] ints = Ints.toArray(list);
Esto le ahorra tener que hacer la conversión de la matriz intermedia que requiere el equivalente de Commons Lang.
Aquí está el código de una sola línea de Java 8 para esto
public int[] toIntArray(List<Integer> intList){
return intList.stream().mapToInt(Integer::intValue).toArray();
}
Con Eclipse Collections , puede hacer lo siguiente si tiene una lista de tipo 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);
Si ya tiene un tipo de colecciones de Eclipse como MutableList
, puede hacer lo siguiente:
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);
Nota: Soy un comendador de Eclipse Collections.
Desafortunadamente, no creo que realmente haya una mejor manera de hacerlo debido a la naturaleza del manejo de Java de los tipos primitivos, el boxeo, las matrices y los genéricos. En particular:
-
List<T>.toArray
no funcionará porque no hay conversión deInteger
aint
- No se puede usar
int
como un argumento de tipo para los genéricos, por lo que tendría que ser un método específico deint
(o uno que usara la reflexión para hacer engaños desagradables).
Creo que hay bibliotecas que tienen versiones generadas automáticamente 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 es así como me temo :(
A pesar de que la clase Arrays
salió antes de que los genéricos llegasen a Java, aún tendría que incluir todas las sobrecargas horribles si se presentara hoy (suponiendo que quiera usar matrices primitivas).
La forma más fácil de hacer esto es hacer uso de Apache Commons Lang . Tiene una práctica clase de ArrayUtils que puede hacer lo que quieras. Utilice el método toPrimitive
con la sobrecarga para una matriz de toPrimitive
Integer
.
List<Integer> 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 dejó de lado. Arriba, elegí crear una lista de enteros del tamaño correcto. También puede usar una matriz de enteros estática de longitud 0 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));
Le recomendaría que use la implementación esquelética de List<?>
De la API de colecciones java. Parece ser muy ú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<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));
}
}
Cuidado con los inconvenientes del boxeo / desempaquetado
Nadie ha mencionado aún las transmisiones agregadas en Java 8, así que aquí va:
int[] array = list.stream().mapToInt(i->i).toArray();
Proceso de pensamiento:
- La
Stream#toArray
simpleStream#toArray
devuelveObject[]
, por lo que no es lo que queremos. Además,Stream#toArray(IntFunction<A[]> generator)
no hace lo que queremos porque el tipoA
genérico no puede representarint
primitivo - por lo que sería bueno tener algún flujo que pudiera manejar el tipo primitivo
int
, porque su métodotoArray
probablemente también devolverá la matrizint[]
(devolver algo más comoObject[]
o incluso unInteger[]
caja no sería natural aquí). Y afortunadamente Java 8 tiene tal flujo:IntStream
Así que ahora, solo tenemos que descubrir cómo convertir nuestro
Stream<Integer>
(que se devolverá delist.stream()
) a eseIntStream
brillante. Aquí el métodomapToInt
viene a rescatar. Todo lo que necesitamos hacer es proporcionar algunos mapas deInteger
aint
. Podríamos usar algo comoInteger#getValue
que devuelveint
: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 compilador sabe que el resultado de este lambda debe ser
int
(lambda enmapToInt
es la implementación de la interfazToIntFunction
que espera el cuerpo paraint applyAsInt(T value)
que se espera que devuelvaint
).Así que simplemente podemos escribir
mapToInt((Integer i)->i)
o más simple (ya que el compilador puede inferir el tipo
Integer i
porqueList<Integer>#stream()
devuelveStream<Integer>
)mapToInt(i -> i)
Realmente no hay forma de "hacer una línea" lo que intentas hacer porque toArray devuelve un Object [] y no puedes convertir desde Object [] a int [] o Integer [] a int []
Si simplemente está asignando un Integer
a un int
entonces debería considerar usar el paralelismo , ya que su lógica de mapeo no se basa en ninguna variable fuera de su alcance.
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 serlo si tiene suficientes datos y núcleos de procesador. Si bien las operaciones agregadas le permiten implementar más fácilmente el paralelismo, aún es su responsabilidad determinar si su aplicación es adecuada para el paralelismo.
Hay dos formas de asignar los enteros a su forma primitiva:
A través de un
ToIntFunction
.mapToInt(Integer::intValue)
A través de unboxing explícito con expresión lambda.
mapToInt(i -> i.intValue())
Vía implícita (auto-) unboxing con expresión lambda.
mapToInt(i -> i)
Dada una lista con un valor null
List<Integer> list = Arrays.asList(1, 2, null, 4, 5);
Aquí hay tres opciones para manejar null
:
Filtra los valores
null
antes de mapear.int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
Asigne los valores
null
a un valor predeterminado.int[] arr = list.parallelStream().map(i -> i == null ? -1 : i).mapToInt(Integer::intValue).toArray();
Manejar
null
dentro de la expresión lambda.int[] arr = list.parallelStream().mapToInt(i -> i == null ? -1 : i.intValue()).toArray();
Usando un lambda puedes hacer esto (compila 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<Integer> inputs = new ArrayList<Integer>(5) { {add(10); add(10);} };
int[] results = transformService.transform(inputs);
}
public interface TransformService {
int[] transform(List<Integer> inputs);
}
Voy a tirar uno más aquí. He notado varios usos de los bucles, pero ni siquiera necesitas nada dentro del bucle. Menciono esto solo porque la pregunta original estaba tratando de encontrar un código menos detallado.
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;
}
Si Java permitiera múltiples declaraciones en un bucle for como lo hace C ++, podríamos ir un paso más allá y hacerlo para (int i = 0, iterador ...
Sin embargo, al final (esta parte es solo mi opinión), si va a tener una función de ayuda o un método para hacer algo por usted, simplemente configúrelo y olvídelo. Puede ser de una sola línea o diez; Si nunca lo miras de nuevo, no sabrás la diferencia.
pruebe también el Dollar ( verifique esta revisión ):
import static com.humaorie.dollar.Dollar.*
...
List<Integer> source = ...;
int[] ints = $(source).convert().toIntArray();
Java 8 nos ha dado una forma fácil de hacer esto a través de secuencias ...
Usando la función de colecciones de stream()
y luego mapeando a ints, obtendrás un IntStream. Con el IntStream
podemos llamar a Array () que nos da int []
int [] ints = list.stream().mapToInt(Integer::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;
int[] toIntArray(List<Integer> list) {
int[] ret = new int[list.size()];
int i = 0;
for (Integer e : list)
ret[i++] = e;
return ret;
}
Un ligero cambio en su código para evitar la indexación de listas caras (ya que una Lista no es necesariamente una Lista de Arrays, pero podría ser una lista vinculada, para la cual el acceso aleatorio es costoso)