2016-05-20 12 views
5

Mi chiedevo se esiste un modo per ottenere quanto segue all'interno di una singola iterazione sull'array. Semplicemente per avere due risultati diversi fuori dal flusso.Calcolo della somma e della somma dei quadrati allo stesso tempo con Stream

double sum = Arrays.stream(doubles).sum(); 
double sumOfSquares = Arrays.stream(doubles).map(d -> d * d).sum(); 
+3

Se si ha bisogno di un sacco di questi tipi di statistiche, la sottoclassi [DoubleSummaryStatistics] (https://docs.oracle.com/javase/8/docs/api/java/util/DoubleSummaryStatistics.html) potrebbe avere senso. – the8472

+2

Domanda correlata (utilizzando l'idea da @ the8472) http://stackoverflow.com/questions/36263352/java-streams-standard-deviation – Tunaki

+6

L'approccio consigliato qui è in effetti la sottoclasse di 'DoubleSummaryStatistics'. Detto questo, stai attento. Abbiamo preso in considerazione l'inclusione della somma dei quadrati in DSS, ma abbiamo scelto di non farlo perché (a) è più un calcolo che molti utenti vogliono, ma soprattutto (b) è molto facile ottenere problemi numerici con la varianza in virgola mobile per somma- dei quadrati. (La quadratura rende i grandi numeri più grandi e piccoli più piccoli, portando al rischio di perdere dati quando li aggiungi.) Vedi Knuth AOCP, vol 2, sez 4.2.2 per maggiori dettagli. –

risposta

13

Beh, si potrebbe con una collezione personalizzata, per esempio:

double[] res = 
    Arrays.stream(doubles) 
      .collect(() -> new double[2], 
        (arr, e) -> {arr[0]+=e; arr[1]+=e*e;}, 
        (arr1, arr2) -> {arr1[0]+=arr2[0]; arr1[1]+=arr2[1];}); 

double sum = res[0]; 
double sumOfSquares = res[1]; 

ma non si guadagna molto di leggibilità, a mio parere, quindi vorrei rimanere con la soluzione passa multipla (o forse basta usare un ciclo for in questo caso).

+0

Grazie mille! Sto ancora imparando i flussi, quindi è davvero utile. – HectorBarbossa