簡體   English   中英

結合兩個流Java 8

[英]Combine two streams Java 8

有沒有辦法結合以下兩種語態?

    Map<Integer,Double> collX = listeAllerPunkte.stream().collect(groupingBy(DataPoint::getId,
                                averagingDouble(DataPoint::getX)));
    Map<Integer,Double> collY = listeAllerPunkte.stream().collect(groupingBy(DataPoint::getId,
                                averagingDouble(DataPoint::getY)));

我有這樣的Class DataPoints

public class DataPoint {

    public final double x;
    public final double y;
    private int Id;

    public DataPoint(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

    public int getId() {
        return Id;
    }
}

Id包含0-5之間的Random值。

listeAllerPunkte是一個包含大量DataPointsList

現在,我想創建一個DataPoint的每個DataPoints與同一列表Id DataPoint應具有相同Id的Datapoints的x and y values的平均值。

使用來自Beginning的兩個Statemantes,我必須從兩個Maps中手動創建DataPoints 有沒有辦法直接在流中創建它們?

一般的解決方案是使用一個收集器,它可以將兩個收集器組合在一起進行處理。 不幸的是,標准API中不存在這樣的收集器,但是這個答案提供了這種收集器的實現。

或者,您可以通過創建自己的類來保存點的摘要,為此特定情況創建解決方案,例如

static class DataPointSummary {
    long count;
    double sumX, sumY;

    public double getAverageX() {
        return count==0? 0: sumX/count;
    }
    public double getAverageY() {
        return count==0? 0: sumY/count;
    }
    public void add(DataPoint p) {
        count++;
        sumX+=p.getX();
        sumY+=p.getY();
    }
    public DataPointSummary merge(DataPointSummary s) {
        count+=s.count;
        sumX+=s.sumX;
        sumY+=s.sumY;
        return this;
    }
    @Override
    public String toString() {
        return "DataPointSummary["+count+" points"
            +", avg x="+getAverageX()+", avg y="+getAverageY()+']';
    }
}

然后你可以收集你的積分

Map<Integer,DataPointSummary> coll = listeAllerPunkte.stream().collect(
    groupingBy(DataPoint::getId, Collector.of(
        DataPointSummary::new, DataPointSummary::add, DataPointSummary::merge)));

請注意,我假設您的方法簽名public double getId()是一個拼寫錯誤,實際上是public int getId() ,否則,您問題中的示例將不起作用。

如果點的坐標具有相同的大小,則上面的摘要實現很有效。 如果在同一組中遇到非常大的值和非常小的值,則可能需要使用誤差補償算法求和。 我建議使用JRE的摘要實現,而不是自己實現它:

static class DataPointSummary {
    final DoubleSummaryStatistics x=new DoubleSummaryStatistics();
    final DoubleSummaryStatistics y=new DoubleSummaryStatistics();

    public double getAverageX() {
        return x.getAverage();
    }
    public double getAverageY() {
        return y.getAverage();
    }
    public void add(DataPoint p) {
        x.accept(p.getX());
        y.accept(p.getY());
    }
    public DataPointSummary merge(DataPointSummary s) {
        x.combine(s.x);
        y.combine(s.y);
        return this;
    }
    @Override
    public String toString() {
        return "DataPointSummary["+x.getCount()+" points"
            +", avg x="+getAverageX()+", avg y="+getAverageY()+']';
    }
}

此變體的使用方式與第一個相同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM