Java-Stream toArray () konvertiert in einen bestimmten Array-Typ

75

Vielleicht ist das sehr einfach, aber ich bin ein Neuling in Java 8-Funktionen und weiß nicht, wie ich das erreichen soll. Ich habe diese einfache Zeile, die den folgenden Text enthält:

"Schlüssel, Name"

und ich möchte diese Zeile in ein String-Array konvertieren und jeden Wert durch das Komma (,) trennen. Ich möchte jedoch auch jedes Feld kürzen, bevor ich das endgültige Array zurückgebe.

Arrays.stream(line.split(",")).map(String::trim).toArray();

Dies gibt jedoch ein Object [] -Array anstelle eines String [] -Arrays zurück. Bei weiterer Prüfung kann ich bestätigen, dass es sich bei dem Inhalt tatsächlich um String-Instanzen handelt, das Array selbst jedoch aus Objektelementen besteht. Lassen Sie mich dies veranschaulichen. Dies sagt der Debugger über das zurückgegebene Objekt:

Object[]:
    0 = (String) "Key"
    1 = (String) "Name"

Soweit ich das beurteilen kann, liegt das Problem im Rückgabetyp des Map-Aufrufs, aber wie kann ich dafür sorgen, dass ein String [] -Array zurückgegeben wird?

arielnmz
quelle

Antworten:

119

Verwenden Sie toArray(size -> new String[size])oder toArray(String[]::new).

String[] strings = Arrays.stream(line.split(",")).map(String::trim).toArray(String[]::new);

Dies ist eigentlich ein Lambda-Ausdruck für

.toArray(new IntFunction<String[]>() {
        @Override
        public String[] apply(int size) {
            return new String[size];
        }
    });

Wenn Sie sagen, konvertieren Sie das Array in ein String-Array gleicher Größe.

Aus den Dokumenten

Die Generatorfunktion verwendet eine Ganzzahl, die der Größe des gewünschten Arrays entspricht, und erzeugt ein Array mit der gewünschten Größe. Dies kann mit einer Array-Konstruktorreferenz kurz ausgedrückt werden:

 Person[] men = people.stream()
                      .filter(p -> p.getGender() == MALE)
                      .toArray(Person[]::new);

Typparameter:

A - der Elementtyp des resultierenden Arrays

Parameter:

Generator - eine Funktion, die ein neues Array des gewünschten Typs und der bereitgestellten Länge erzeugt

Mritunjay
quelle
Können Sie bitte erklären, was die String[]::newMethodenreferenz tut und wie ich dasselbe mit einem regulären Lambda-Ausdruck tun kann? (Ich sehe, dass es einen "Wert" vom Typ int ergibt, aber es macht für mich keinen Sinn).
Arielnmz
2
Natürlich ist es besser, die Parametervariable " size" anstelle von " value" zu benennen , daher ist die Bedeutung offensichtlich.
Holger
3
Übrigens wird der trimSchritt veraltet, wenn Sie den Leerraum zum Teil des Trennzeichens machen, z. B. line.split("\\s*,\\s*")weil er überhaupt nicht in den Ergebniszeichenfolgen enthalten ist. Dann brauchen Sie den Stream-Vorgang überhaupt nicht : String[] result=line.split("\\s*,\\s*");. Oder Sie können verwenden String[] result=line.split(","); Arrays.asList(result).replaceAll(String::trim);. Sie brauchen nicht für jede Aufgabe einen Stream…
Holger
2
@Holger, änderte den Variablennamen, gültiger Punkt. Über den zweiten Kommentar habe ich nur versucht, die Frage zu beantworten und nichts geändert, was bereits da war.
Mritunjay
Es tut mir leid, Necro-Post zu schreiben, aber das Ziel des Codes war es, die Verwendung von Map zu entschuldigen. In diesem Fall habe ich tatsächlich versucht, eine Verwendung für Streams zu erzwingen.
Arielnmz
5

String[]::newist eine Funktion, die die new"Pseudomethode" für den String[]Typ String::trimaufruft, genau wie eine Funktion, die die reale trimMethode des String-Typs aufruft . Der String::newvon toArray an die Funktion übergebene Wert entspricht der Größe der Auflistung auf der rechten Seite des Methodenaufrufs .toArray ().

Wenn Sie ersetzt String[]::newmit n->new String[n]Ihnen könnte mit der Syntax bequemer wie Sie ersetzen könnten String::trimmit dem weniger kühlens->s.trim()

Paul Buis
quelle