2016-08-07 23 views
2
class Stock{ 
    double profit; 
    double profitPercentage; 
    public double getProfit(){ 
     return profit; 
    } 
    public double getProfitPercentage(){ 
     return profitPercentage; 
    } 
} 
List<Stock> stocks = getAllStocks(); 
stocks.stream.collect(Collectors.summarizingDouble(Stock:getProfit)).getSum(); 
stocks.stream.collect(Collectors.summarizingDouble(Stock:getProfitPercentage)).getSum(); 

sammeln Ich konnte nicht herausfinden, wie in Single-Pass-Stream zu tun. Jede Hilfe oder ein Zeiger wäre gut.Wie zwei Summen aus einem Stream in Java 8

+1

Sie suchen etwas [so] (http://stackoverflow.com/a/30211021/1743880). – Tunaki

+0

Der Link zeigte etwas wie groupby und sum. Für mich benötige ich eine Summe von 2 Feldern und keine Gruppe durch. –

+0

Summieren Sie alle Profite und Gewinnprozente? –

Antwort

1

Der direkte Weg besteht darin, eine benutzerdefinierte Kollektorklasse zu erstellen.

public class StockStatistics { 

    private DoubleSummaryStatistics profitStat = new DoubleSummaryStatistics(); 
    private DoubleSummaryStatistics profitPercentageStat = new DoubleSummaryStatistics(); 

    public void accept(Stock stock) { 
     profitStat.accept(stock.getProfit()); 
     profitPercentageStat.accept(stock.getProfitPercentage()); 
    } 

    public StockStatistics combine(StockStatistics other) { 
     profitStat.combine(other.profitStat); 
     profitPercentageStat.combine(other.profitPercentageStat); 
     return this; 
    } 

    public static Collector<Stock, ?, StockStatistics> collector() { 
     return Collector.of(StockStatistics::new, StockStatistics::accept, StockStatistics::combine); 
    } 

    public DoubleSummaryStatistics getProfitStat() { 
     return profitStat; 
    } 

    public DoubleSummaryStatistics getProfitPercentageStat() { 
     return profitPercentageStat; 
    } 

} 

Diese Klasse dient als Wrapper um zwei DoubleSummaryStatistics. Sie delegiert jedes Mal an sie, wenn ein Element akzeptiert wird. In Ihrem Fall, da Sie nur an der Summe interessiert sind, könnten Sie sogar eine Collectors.summingDouble anstelle von DoubleSummaryStatistics verwenden. Außerdem gibt es die zwei Statistiken mit getProfitStat und getProfitPercentageStat zurück; alternativ könnten Sie eine Finisher-Operation hinzufügen, die eine double[] zurückgibt, die nur beide Summen enthält.

Dann können Sie verwenden

StockStatistics stats = stocks.stream().collect(StockStatistics.collector()); 
System.out.println(stats.getProfitStat().getSum()); 
System.out.println(stats.getProfitPercentageStat().getSum()); 

Eine generische Art und Weise ist ein Sammler der Lage Paarung andere Sammler zu schaffen. Sie können den pairing Collector geschrieben in this answer und auch in the StreamEx library verwenden.

double[] sums = stocks.stream().collect(MoreCollectors.pairing(
    Collectors.summingDouble(Stock::getProfit), 
    Collectors.summingDouble(Stock::getProfitPercentage), 
    (sum1, sum2) -> new double[] { sum1, sum2 } 
)); 

Die Summe des Gewinns in sums[0] und die Summe des Gewinns Prozentsatz in sums[1] wird sein wird. In diesem Snippet werden nur die Summen und nicht die gesamten Werte gespeichert.