2014-06-24 12 views
153

Ich habe gerade die neuen Java 8-Stream-Funktionen entdeckt. Von Python kommend, habe ich mich gefragt, ob es nun eine gute Möglichkeit gibt, Operationen auf Arrays wie Summieren durchzuführen, indem man zwei Arrays auf "one line python" -Methode multipliziert.Java 8 Stream und Betrieb auf Arrays

Dank

Antwort

248

Es gibt neue Methoden zu java.util.Arrays hinzugefügt ein Array in ein Java 8 Strom umzuwandeln, die dann zum Summieren usw. verwendet werden können

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

Multipliziert man zwei Arrays ein wenig schwieriger, weil Ich kann mir keinen Weg vorstellen, den Wert UND den Index gleichzeitig als 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]); 

EDIT

Commenter @Holger weist darauf hin, Sie map Methode anstelle von forEach wie diese verwenden:

int[] result = IntStream.range(0, a.length).map(i -> a[i] * b[i]).toArray(); 
+11

'int [] result = IntStream.range (0, a.length) .map (i-> a [i] * b [i]) toArray();.' – Holger

+0

@Holger ja das würde auch funktionieren. Obwohl Sie wahrscheinlich "mapToInt" verwenden möchten, um Boxen zu vermeiden. – dkatzel

+0

Letzteres entspricht einer Simulation von zip, bei der Sie den Speicher für das Ergebnis vorab reservieren müssen. Ich frage mich, warum es keine Zip in der Streams-Bibliothek gibt? –

51

Sie ein Array in einen Strom verwandeln kann Arrays.stream() unter Verwendung:

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

Sobald Sie Ihren Stream haben, können Sie eine der in the documentation beschriebenen Methoden verwenden, wie sum() oder was auch immer. Sie können map oder filter wie in Python durch den jeweiligen 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 fertig sind Ändern Sie dann toArray() nennen es in ein Array zurück zu konvertieren 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(); 
5

Seien Sie vorsichtig, wenn Sie mit großen Zahlen zu tun haben.

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

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

long sum = Arrays.stream(arr).mapToLong(Long::valueOf).sum(); // Correct 
1

Bitte beachten Sie, dass Arrays.stream (arr) ein LongStream erstellen (oder IntStream, ...) statt Strom, so dass die Kartenfunktion kann nicht verwendet werden, um die Art zu ändern. Aus diesem Grund werden die Funktionen .mapToLong, mapToObject, ... bereitgestellt.

Werfen Sie einen Blick auf why-cant-i-map-integers-to-strings-when-streaming-from-an-array