繁体   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