Wie man eine Liste in ein Array in Java umwandelt
Java-Liste mit toArray und Stream-Ansätzen in ein Array umwandeln — typsicher und für primitive Typen.
Eine List und ein Array enthalten dieselben Elemente, bieten jedoch unterschiedliche APIs: Eine List ist dynamisch und verfügt über vielfältige Methoden, während ein Array eine feste Länge hat und von vielen älteren oder Low-Level-APIs erwartet wird. Die Konvertierung von einem zum anderen ist in modernem Java eine Einzeiler-Aufgabe — die einzige echte Entscheidung besteht darin, welche Form am verständlichsten ist und ob ein Objekt-Array oder ein primitives Array benötigt wird. Diese Seite behandelt die typisierte toArray-Überladung, den Constructor-Reference-Ansatz ab Java 11, den Stream-Weg für primitive Arrays und die Fallstricke des argumentlosen toArray().
Der idiomatische Weg: toArray mit einem typisierten Array
List.toArray(T[]) gibt ein stark typisiertes Array zurück. Übergebe ein nulllanges Array des Elementtyps und lass das JDK die Größe des Ergebnisses bestimmen:
List<String> names = List.of("Ann", "Bob", "Cy");
String[] arr = names.toArray(new String[0]);Das Argument new String[0] trägt den Typ (String[]), nicht einen vorausgesizten Puffer. Auf modernen JVMs ist die Leerarray-Form die empfohlene — sie ist genauso schnell wie ein passend dimensioniertes Array und vermeidet den Fehler, bei dem ein zu kleines Array neu allokiert wird und ein zu großes nachfolgende null-Werte hinterlässt. Verwende diese Form immer dann, wenn du ein Array vom Object-Typ wie String[], Integer[] oder eine eigene Klasse benötigst.
Die Java-11+-Form: eine Array-Constructor-Reference
Seit Java 11 kann man statt eines literalen leeren Arrays eine Array-Constructor-Reference übergeben. Sie sagt genau das, was sie bedeutet — „gib mir ein String[]":
String[] arr = names.toArray(String[]::new);Dies kompiliert zum selben Ergebnis wie new String[0], ist aber klarer lesbar. Beachte, dass das argumentlose toArray() eine Falle ist: Es gibt immer Object[] zurück, nie String[], daher wirft das Casten des Ergebnisses auf String[] zur Laufzeit eine ClassCastException.
| Ansatz | Ergebnistyp | Hinweise |
|---|---|---|
list.toArray(new String[0]) | String[] | Empfohlen für Objekt-Arrays |
list.toArray(String[]::new) | String[] | Java 11+, klarste Form |
list.toArray() | Object[] | Verliert den Elementtyp; selten gewünscht |
list.stream().mapToInt(...).toArray() | int[] | Einziger Weg zu einem primitiven Array |
Primitive Arrays über einen Stream
toArray kann nur Arrays von Objekten erzeugen. Eine List<Integer> kann nicht direkt zu einem int[] werden — Autoboxing erstreckt sich nicht auf Arrays. Verwende einen Stream, um jedes Element zu unboxen:
List<Integer> nums = List.of(10, 20, 30);
int[] prim = nums.stream().mapToInt(Integer::intValue).toArray();Dasselbe Muster liefert long[] (mapToLong) und double[] (mapToDouble). Es gibt keinen JDK-Shortcut für primitive Arrays, daher ist der Stream der idiomatische Weg.
Ein ausgearbeitetes Beispiel
Dieses Programm führt jeden Ansatz nebeneinander aus, gibt den Laufzeittyp aus, den das argumentlose toArray tatsächlich zurückgibt, und beweist, dass das resultierende Array eine unabhängige Kopie ist — das Bearbeiten des Arrays berührt die ursprüngliche Liste nicht.
Was aus der Ausgabe zu entnehmen ist:
toArray(new String[0])undtoArray(String[]::new)geben beide[Ann, Bob, Cy]aus — sie sind zwei Schreibweisen derselben typisierten Konvertierung, und du kannst diejenige verwenden, die in deinem Code besser lesbar ist.- Das argumentlose
toArray()meldet seinen Laufzeittyp alsObject[], nicht alsString[]— ein konkreter Beweis, dass es den Elementtyp löscht und warum du das Casten seines Ergebnisses vermeiden solltest. - Die
List<Integer>wird erst nachmapToIntzu einem echtenint[]; das ausgegebene[10, 20, 30]ist ein primitives Array, keinInteger[], sodass kein Boxing bestehen bleibt. Arrays.stream(prim).sum()gibt60aus und bestätigt, dass das Ergebnis ein nutzbares primitives Array ist, das direkt in numerische Stream-Operationen eingespeist werden kann.- Nach
a1[0] = "ZZ"gibt das Array[ZZ, Bob, Cy]aus, während die Liste weiterhin[Ann, Bob, Cy]ausgibt —toArraygibt eine unabhängige Kopie zurück, sodass Änderungen am Array niemals in die Quellliste zurückfließen.