Konvertieren eines Arrays von Objekten in ein Array ihrer primitiven Typen

80

Wenn Sie ein Array von Java-Objekten haben, die einen primitiven Typ haben (z. B. Byte, Integer, Char usw.). Gibt es eine gute Möglichkeit, es in ein Array vom primitiven Typ umzuwandeln? Dies kann insbesondere erfolgen, ohne dass ein neues Array erstellt und der Inhalt durchlaufen werden muss.

So zum Beispiel gegeben

Integer[] array

Was ist der beste Weg, dies in umzuwandeln

int[] intArray

Leider müssen wir dies ziemlich häufig tun, wenn wir eine Schnittstelle zwischen Hibernate und einigen Bibliotheken von Drittanbietern herstellen, über die wir keine Kontrolle haben. Es scheint, dass dies eine recht häufige Operation ist, daher wäre ich überrascht, wenn es keine Abkürzung gibt.

Danke für Ihre Hilfe!

Il-Bhima
quelle

Antworten:

40

Leider gibt es auf der Java-Plattform nichts, was dies tut. Übrigens müssen Sie auch nullElemente im Integer[]Array explizit behandeln (was intwerden Sie für diese verwenden?).

Zach Scrivena
quelle
6
Guter Punkt über die Nullen. Für meine Zwecke hätte ich akzeptiert, dass eine Ausnahme ausgelöst wird, wenn einer der Einträge null ist, genauso wie eine NullPointerException ausgelöst wird, wenn Sie ein Objekt entpacken.
Il-Bhima
2
Diese Antwort ist mit Java 8 nicht mehr korrekt, siehe Alex 'Antwort .
Robinst
90

Wieder einmal ist Apache Commons Lang dein Freund. Sie bieten ArrayUtils.toPrimitive (), das genau das tut, was Sie brauchen. Sie können angeben, wie Sie mit Nullen umgehen möchten.

Guillaume
quelle
69

Mit in Java 8 eingeführten Streams ist dies möglich:

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

Derzeit gibt es jedoch nur primitive Streams für int, longund double. Wenn Sie in einen anderen primitiven Typ konvertieren müssen, z. B. byteden kürzesten Weg ohne externe Bibliothek, ist dies:

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

Oder die for-Schleife kann durch einen Stream ersetzt werden, wenn Sie möchten:

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

Alle diese werden ein werfen, NullPointerExceptionwenn eines Ihrer Elemente sind null.

Alex - GlassEditor.com
quelle
2
Stattdessen Integer::intValuekönnen Sie auch verwenden i -> i(was Unboxing verwendet).
Robinst
1
@robinst Und Unboxing fordert der Compiler Integer::intValuefür Sie auf. Warum also ein neues Lambda erstellen, wenn die Methode sofort verfügbar ist?
Andreas
@Andreas Nur eine andere Option aufzulisten, die Sie auswählen, ist eine Frage des Codestils / der persönlichen Präferenz. Ich habe die beiden Ansätze auch mit einem Mikrobenchmark versehen (unter Verwendung von JMH), und sie haben die gleiche Leistung.
Robinst
Bei Verwendung des ersten veröffentlichten Code-Snippets wurde der Fehler "Nicht statische Methode kann nicht im statischen Kontext verwendet werden" angezeigt. Ich habe stattdessen Folgendes getan: Ich int[] ints = Arrays.stream(objects).mapToInt(i -> Integer.parseInt(i.toString())).toArray(); hoffe, dies ist hilfreich für alle, die das gleiche Problem haben. Und wenn jemand einen besseren Weg kennt, lass es mich wissen.
Kartik Chugh
Dies sollte heutzutage die akzeptierte Antwort sein. Danke Alex.
Per Lundberg
27

Verwenden von Guave :

int[] intArray = Ints.toArray(Arrays.asList(array));

Dokumentation:

Paul Bellora
quelle
3

Dies kann insbesondere erfolgen, ohne dass ein neues Array erstellt und der Inhalt durchlaufen werden muss.

Sie können ein Array von Integer in Java nicht in int konvertieren (dh Sie können den Typ der Elemente eines Arrays nicht ändern). Sie müssen also entweder ein neues int [] -Array erstellen und den Wert der Integer-Objekte in dieses Array kopieren, oder Sie können einen Adapter verwenden:

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

Dies kann Ihren Code ein wenig lesbarer machen und das IntAdapter-Objekt belegt nur wenige Bytes Speicher. Der große Vorteil eines Adapters ist, dass Sie hier Sonderfälle behandeln können:

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

Eine andere Lösung ist die Verwendung von Commons Primitives, die viele vordefinierte Adapter enthalten. Schauen Sie sich in Ihrem Fall ListIntList an .

Aaron Digulla
quelle
2

Oder mach es einfach, wenn du es nur einmal machst. Aber Sie haben nicht über Integer! = Null-Fall gesprochen.

    //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
quelle
1

Die Verwendung von Dollar ist einfach wie folgt:

Integer[] array = ...;
int[] primitiveArray = $(array).toIntArray();
dfa
quelle
6
Dies scheint nicht Java zu sein, zumindest nicht Java 1.6 oder 1.7.
Lordalcol
2
@ LorDalCol Dollar ist eigentlich eine Java-Bibliothek
Jaroslav Záruba
1
Es ist möglich, eine Java-Methode zu benennen $! Ich glaube nicht, dass es ermutigt wird ...
Ole VV