2016-05-20 11 views
5

Ich fragte mich, ob es möglich ist, das folgende innerhalb einer einzigen Iteration über das Array zu erreichen. Einfach zwei verschiedene Ergebnisse aus dem Stream haben.Rechnen Summe und Summe der Quadrate gleichzeitig mit Streams

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

Wenn Sie feststellen, benötigen Sie viele dieser Arten von Statistiken dann Unterklasse [DoubleSummaryStatistics] (https://docs.oracle.com/javase/8/docs/api/java/util/DoubleSummaryStatistics.html) sinnvoll sein könnte. – the8472

+2

Verwandte Frage (mit der Idee von @ the8472) http://StackOverflow.com/Questions/36263352/Java-Streams-Standard-Abweichung – Tunaki

+6

Der empfohlene Ansatz hier ist in der Tat zu Unterklasse "DoubleSummaryStatistics". Das heißt, sei vorsichtig. Wir haben in Betracht gezogen, die Summe der Quadrate in DSS zu berücksichtigen, wählten aber nicht, weil (a) mehr Berechnungen von vielen Benutzern gewünscht werden, aber noch wichtiger (b) es sehr einfach ist, numerisches Problem mit der Fließkomma-Berechnung zu bekommen. von Quadraten. (Quadrierung macht große Zahlen größer und kleine Zahlen kleiner, was zu dem Risiko des Verlusts von Daten führt, wenn Sie sie hinzufügen.) Siehe Knuth AOCP, Band 2, Abschnitt 4.2.2 für weitere Details. –

Antwort

13

Nun, man könnte mit einem benutzerdefinierten Sammler, zum Beispiel:

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]; 

aber Sie haben nicht viel Lesbarkeit meiner Meinung nach gewinnen, so würde ich mit der mehrfachen Durchgängen Lösung bleiben (oder vielleicht Verwenden Sie in diesem Fall einfach eine For-Schleife.

+0

Vielen Dank! Ich lerne immer noch Streams, also ist es wirklich hilfreich. – HectorBarbossa