Wie man ein Array in Java ausgibt
Java-Arrays lesbar ausgeben mit Arrays.toString, Arrays.deepToString und streambasierter Formatierung.
Ein Array direkt an System.out.println zu übergeben gibt fast nie das gewünschte Ergebnis — statt der Elemente erscheint etwas wie [I@1b6d3586. Arrays überschreiben toString() nicht, daher gibt die Standard-Object-Version den Typ und einen Identitäts-Hash aus. Dieses Kapitel zeigt die idiomatischen Lösungen: Arrays.toString für eindimensionale Arrays, Arrays.deepToString für verschachtelte, String.join für benutzerdefinierte Trennzeichen und eine manuelle Schleife, wenn vollständige Kontrolle benötigt wird.
Warum ein einfaches Ausgeben fehlschlägt
Das Standard-toString(), das ein Array von Object erbt, gibt eine Klassenbezeichnung plus einen Hash-Code zurück — nicht den Inhalt:
int[] numbers = {3, 1, 4};
System.out.println(numbers); // [I@1b6d3586
System.out.println("" + numbers); // same reference stringDas [I bedeutet "Array von int"; das Hex nach @ ist der Identitäts-Hash, der sich zwischen Läufen ändert. Die Verkettung des Arrays in einen String hilft nicht, da die Verkettung ebenfalls toString() aufruft. Die Lösung besteht darin, einen Hilfsaufruf zur Formatierung der Elemente zu verwenden.
Arrays.toString für eine Dimension
java.util.Arrays.toString durchläuft ein eindimensionales Array und gibt einen lesbaren, durch Komma getrennten String in eckigen Klammern zurück:
int[] numbers = {3, 1, 4, 1, 5};
System.out.println(Arrays.toString(numbers)); // [3, 1, 4, 1, 5]
String[] words = {"alpha", "beta"};
System.out.println(Arrays.toString(words)); // [alpha, beta]Die Methode ist für jeden primitiven Array-Typ (int[], double[], boolean[], …) und für Object[] überladen, funktioniert also mit jedem flachen Array. Bei Objekt-Arrays ruft sie das eigene toString() jedes Elements auf.
Arrays.deepToString für verschachtelte Arrays
Arrays.toString geht nur eine Ebene tief. Bei einem 2D-Array formatiert es das äußere Array, gibt aber jedes innere Array als Referenz aus. Verwende Arrays.deepToString, um rekursiv durch jede Ebene zu gehen:
int[][] grid = {{1, 2}, {3, 4}};
System.out.println(Arrays.toString(grid)); // [[I@..., [I@...]
System.out.println(Arrays.deepToString(grid)); // [[1, 2], [3, 4]]Greife auf deepToString zurück, wenn das Array andere Arrays enthält — Matrizen, unregelmäßige Arrays, Arrays von Arrays von Objekten.
| Ansatz | Am besten für | Ausgabestil |
|---|---|---|
Arrays.toString | 1D primitive oder Objekt-Arrays | [a, b, c] |
Arrays.deepToString | verschachtelte / mehrdimensionale Arrays | [[a, b], [c, d]] |
String.join | String[] mit benutzerdefiniertem Trennzeichen | a, b, c (ohne Klammern) |
manuelle Schleife / StringBuilder | vollständige Kontrolle über das Format | alles, was du aufbaust |
Benutzerdefinierte Formatierung
Wenn das Format mit eckigen Klammern nicht das gewünschte ist, verbindet String.join ein String[] (oder jedes CharSequence-Iterable) mit einem Trennzeichen deiner Wahl und ohne umgebende Klammern:
String[] words = {"alpha", "beta", "gamma"};
System.out.println(String.join(" | ", words)); // alpha | beta | gammaFür Nicht-String-Arrays oder vollständig benutzerdefinierte Ausgaben gibt eine Schleife mit einem StringBuilder vollständige Kontrolle über Trennzeichen, Präfixe und die Formatierung einzelner Elemente. Streams sind eine weitere Option: Arrays.stream(arr).mapToObj(String::valueOf).collect(Collectors.joining(", ")).
Ein ausführbares Beispiel
Das folgende Programm stellt die Ansätze gegenüber: Arrays.toString auf flachem int[] und String[], den Unterschied zwischen flach und tief bei einem 2D-Array, String.join für ein benutzerdefiniertes Trennzeichen und einen manuell aufgebauten StringBuilder. Die shallow-Zeile prüft, ob das flache toString des 2D-Arrays noch innere Referenzen enthält, und gibt daher ein stabiles true statt eines laufvariablen Hashs aus.
Was man aus der Ausführung mitnehmen kann:
toString: [3, 1, 4, 1, 5]zeigt, wieArrays.toStringein flachesint[]in lesbaren, eingeklammerten Text umwandelt.words: [alpha, beta, gamma]bestätigt, dass dieselbe Methode bei Objekt-Arrays funktioniert, indem sie dastoString()jedes Elements aufruft.shallow: truebeweist, dassArrays.toStringbei einem 2D-Array die inneren Arrays als[[I@...-Referenzen belässt, weshalb das Ergebnis mit[[I@beginnt.deep: [[1, 2], [3, 4]]zeigt, wieArrays.deepToStringrekursiv in die verschachtelten Arrays eindringt, um jedes Element auszugeben.joined: alpha | beta | gammaundmanual: {3; 1; 4; 1; 5}zeigen, wieString.joinund eineStringBuilder-Schleife klammernfreie, benutzerdefiniert getrennte Ausgaben erzeugen.