2014-06-24 19 views
153

Ho appena scoperto le nuove funzionalità di streaming di Java 8. Venendo da Python, mi stavo chiedendo se ci fosse ora un modo pulito per fare operazioni su array come sommare, moltiplicando due array in un modo "pythoniano a una linea"?Java 8 Stream e operazioni sugli array

Grazie

risposta

248

Ci sono nuovi metodi aggiunti a java.util.Arrays per convertire un array in un flusso Java 8 che può quindi essere utilizzato per sommare ecc

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

Moltiplicando due array è un po 'più difficile perché Non riesco a pensare a un modo per ottenere il valore AND l'indice contemporaneamente all'operazione Stream. Questo significa che probabilmente devi scorrere gli indici dell'array.

//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 sottolinea è possibile utilizzare il metodo map invece di forEach come questo:

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 si che funzionerebbe anche. Anche se probabilmente vorrai usare 'mapToInt' per evitare il pugilato. – dkatzel

+0

Questo ultimo equivale a una simulazione di zip in cui è necessario preallocare lo spazio di archiviazione per il risultato. Mi chiedo perché non ci siano zip nella libreria Streams? –

51

È possibile attivare una matrice in un flusso utilizzando Arrays.stream():

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

Una volta ottenuto il flusso, è possibile utilizzare uno dei metodi descritti in the documentation, ad esempio sum() o qualsiasi altra cosa. È possibile map o filter come in Python chiamando i metodi flusso rilevanti con una funzione lambda:

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

Una volta fatto modificare il flusso, è quindi chiamare toArray() per riconvertirlo in un array da utilizzare altrove:

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

Fare attenzione se si ha a che fare con grandi numeri.

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

La somma sopra non è 2 * Integer.MIN_VALUE. In questo caso è necessario farlo.

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

prega di notare che Arrays.stream (arr) creare un LongStream (o IntStream, ...) invece di stream in modo che la funzione di mappa non può essere utilizzato per modificare il tipo. Questo è il motivo per cui vengono fornite le funzioni mapToLong, mapToObject, ....

Date un'occhiata a why-cant-i-map-integers-to-strings-when-streaming-from-an-array

Problemi correlati