Conversión de una matriz de objetos en una matriz de sus tipos primitivos

80

Si tiene una matriz de objetos Java que tienen un tipo primitivo (por ejemplo, Byte, Integer, Char, etc.). ¿Hay alguna forma ordenada de convertirlo en una matriz del tipo primitivo? En particular, esto se puede hacer sin tener que crear una nueva matriz y recorrer el contenido.

Entonces, por ejemplo, dado

Integer[] array

¿Cuál es la mejor forma de convertir esto en

int[] intArray

Desafortunadamente, esto es algo que tenemos que hacer con bastante frecuencia cuando interactuamos entre Hibernate y algunas bibliotecas de terceros sobre las que no tenemos control. Parece que esta sería una operación bastante común, por lo que me sorprendería que no hubiera atajos.

¡Gracias por tu ayuda!

Il-Bhima
fuente

Respuestas:

40

Desafortunadamente, no hay nada en la plataforma Java que haga esto. Por cierto, también necesita manejar explícitamente nullelementos en la Integer[]matriz (¿ intqué va a usar para ellos?).

Zach Scrivena
fuente
6
Buen punto sobre los nulos. Para mis propósitos, habría aceptado que se lanzara una excepción si una de las entradas es nula, de la misma manera que se lanza una NullPointerException cuando desempaqueta un objeto.
Il-Bhima
2
Esta respuesta ya no es precisa con Java 8, consulte la respuesta de Alex .
robinst
69

Con las transmisiones introducidas en Java 8, esto se puede hacer:

int[] intArray = Arrays.stream(array).mapToInt(Integer::intValue).toArray();

Sin embargo, en la actualidad hay corrientes única primitivas para int, longy double. Si necesita convertir a otro tipo primitivo, como byteel camino más corto sin una biblioteca externa, es este:

byte[] byteArray = new byte[array.length];
for(int i = 0; i < array.length; i++) byteArray[i] = array[i];

O el bucle for se puede reemplazar con una secuencia si lo desea:

IntStream.range(0, array.length).forEach(i -> byteArray[i] = array[i]);

Todos estos arrojarán un NullPointerExceptionsi alguno de sus elementos lo es null.

Alex - GlassEditor.com
fuente
2
En lugar de Integer::intValue, también puede usar i -> i(que usa unboxing).
robinst
1
@robinst Y unboxing lo llama el compilador Integer::intValue, entonces, ¿por qué crear una nueva lambda, cuando el método está disponible?
Andreas
@Andreas Simplemente enumerar otra opción, la que elija es una cuestión de estilo de código / preferencia personal. También hice microbenchmarked (usando JMH) los dos enfoques, y tienen el mismo rendimiento.
robinst
Usar el primer fragmento de código publicado me estaba dando un error de "No se puede usar un método no estático en un contexto estático", así que en su lugar lo hice: int[] ints = Arrays.stream(objects).mapToInt(i -> Integer.parseInt(i.toString())).toArray(); Espero que esto sea útil para cualquiera con el mismo problema. Y si alguien conoce una manera mejor, hágamelo saber.
Kartik Chugh
Esta debería ser la respuesta aceptada hoy en día. Gracias Alex.
Per Lundberg
3

En particular, esto se puede hacer sin tener que crear una nueva matriz y recorrer el contenido.

No puede convertir una matriz de Integer a int (es decir, no puede cambiar el tipo de los elementos de una matriz) en Java. Por lo tanto, debe crear una nueva matriz int [] y copiar el valor de los objetos Integer en ella o puede usar un adaptador:

class IntAdapter {
    private Integer[] array;
    public IntAdapter (Integer[] array) { this.array = array; }
    public int get (int index) { return array[index].intValue(); }
}

Esto puede hacer que su código sea un poco más legible y el objeto IntAdapter solo consumirá unos pocos bytes de memoria. La gran ventaja de un adaptador es que puede manejar casos especiales aquí:

class IntAdapter {
    private Integer[] array;
    public int nullValue = 0;
    public IntAdapter (Integer[] array) { this.array = array; }
    public int get (int index) { 
        return array[index] == null ? nullValue : array[index].intValue();
    }
}

Otra solución es utilizar Commons Primitives, que contiene muchos adaptadores predefinidos. En su caso, eche un vistazo a ListIntList .

Aaron Digulla
fuente
2

O simplemente hazlo de la manera fácil si lo vas a hacer solo una vez. Pero no has hablado de Integer! = Null case.

    //array is the Integer array
    int[] array2 = new int[array.length];
    int i=0;
    for (Integer integer : array) {
        array2[i] = integer.intValue();
        i++;
    }
Jens Jansson
fuente
1

usar Dollar es tan simple como:

Integer[] array = ...;
int[] primitiveArray = $(array).toIntArray();
dfa
fuente
6
Esto no parece ser Java, al menos no Java 1.6 o 1.7.
Lordalcol
2
@LorDalCol Dollar es en realidad una biblioteca de Java
Jaroslav Záruba
1
¡Es posible nombrar un método Java $! No creo que se animó, aunque ...
Ole VV