Java 8 Stream und Betrieb auf Arrays

197

Ich habe gerade die neuen Java 8-Stream-Funktionen entdeckt. Als ich aus Python kam, fragte ich mich, ob es jetzt eine gute Möglichkeit gibt, Operationen an Arrays wie Summieren durchzuführen und zwei Arrays auf eine "einzeilige pythonische" Weise zu multiplizieren.

Vielen Dank

BlackLabrador
quelle

Antworten:

294

Es wurden neue Methoden hinzugefügt, java.util.Arraysum ein Array in einen Java 8-Stream zu konvertieren, der dann zum Summieren usw. verwendet werden kann.

int sum =  Arrays.stream(myIntArray)
                 .sum();

Das Multiplizieren von zwei Arrays ist etwas schwieriger, da ich mir keine Möglichkeit vorstellen kann, den Wert UND den Index gleichzeitig mit einer Stream-Operation zu erhalten. Dies bedeutet, dass Sie wahrscheinlich über die Indizes des Arrays streamen müssen.

//in this example a[] and b[] are same length
int[] a = ...
int[] b = ...

int[] result = new int[a.length];

IntStream.range(0, a.length)
         .forEach(i -> result[i] = a[i] * b[i]);

BEARBEITEN

Commenter @Holger weist darauf hin, dass Sie die mapMethode anstelle der folgenden verwenden forEachkönnen:

int[] result = IntStream.range(0, a.length).map(i -> a[i] * b[i]).toArray();
dkatzel
quelle
13
int[] result=IntStream.range(0, a.length).map( i->a[i]* b[i]).toArray();
Holger
2
@ Holger ja das würde auch funktionieren. Obwohl Sie wahrscheinlich verwenden möchten mapToInt, um Boxen zu vermeiden.
Dkatzel
Letzteres entspricht einer Simulation von zip, bei der Sie den Speicher für das Ergebnis vorab zuweisen müssen. Ich frage mich, warum es in der Streams-Bibliothek keine Zip gibt.
Reb.Cabin
Nach dieser SO-Antwort wurde eine Zip-Datei in einer früheren Beta von Java 8 entfernt. Zum Glück hatte das Poster die Quelle und es ist in der Antwort. Ich habe den Code mehrmals verwendet und er scheint sehr gut zu funktionieren.
sparc_spread
@dkatzel - Da es sich bereits um einen IntStream handelt, benötigt "map" einen IntUnaryOperator, sodass kein Boxen erforderlich ist.
M. Justin
58

Sie können ein Array in einen Stream verwandeln, indem Sie Folgendes verwenden Arrays.stream():

int[] ns = new int[] {1,2,3,4,5};
Arrays.stream(ns);

Sobald Sie Ihren Stream haben, können Sie eine der in der Dokumentation beschriebenen Methoden verwenden , wie sum()oder was auch immer. Sie können mapoder filtermöchten in Python, indem Sie die relevanten Stream-Methoden mit einer Lambda-Funktion aufrufen:

Arrays.stream(ns).map(n -> n * 2);
Arrays.stream(ns).filter(n -> n % 4 == 0);

Sobald Sie Ihren Stream geändert haben, rufen Sie ihn toArray()auf, um ihn wieder in ein Array zu konvertieren und an anderer Stelle zu verwenden:

int[] ns = new int[] {1,2,3,4,5};
int[] ms = Arrays.stream(ns).map(n -> n * 2).filter(n -> n % 4 == 0).toArray();
Ian Knight
quelle
9

Seien Sie vorsichtig, wenn Sie mit großen Zahlen umgehen müssen.

int[] arr = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE};
long sum = Arrays.stream(arr).sum(); // Wrong: sum == 0

Die obige Summe ist nicht 2 * Integer.MIN_VALUE. In diesem Fall müssen Sie dies tun.

long sum = Arrays.stream(arr).mapToLong(Long::valueOf).sum(); // Correct
Sanghyun Lee
quelle
3

Bitte beachten Sie, dass Arrays.stream (arr) einen LongStream (oder IntStream, ...) anstelle von Stream erstellt, sodass die Map-Funktion nicht zum Ändern des Typs verwendet werden kann. Aus diesem Grund werden die Funktionen .mapToLong, mapToObject, ... bereitgestellt.

Werfen Sie einen Blick darauf, warum-i-map-Ganzzahlen-zu-Zeichenfolgen-beim-Streaming-von-einem-Array-sind

Rafael
quelle