将两个流合并到Java8中

将两个流合并到Java8中,java,java-8,java-stream,Java,Java 8,Java Stream,有没有办法将以下两种状态结合起来 Map<Integer,Double> collX = listeAllerPunkte.stream().collect(groupingBy(DataPoint::getId, averagingDouble(DataPoint::getX))); Map<Integer,Double> collY = listeAllerPunkte.stream().

有没有办法将以下两种状态结合起来

    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)));
Id
包含一个介于
0-5
之间的随机值

listallerpunkte
是一个包含大量数据点的
列表

现在我想为列表中具有相同
Id
的每个
DataPoints
创建一个
DataPoint
数据点
应具有具有相同
Id
的数据点的
x和y值的平均值

有了这两个状态,我必须从两个映射中手动创建
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)));
此变体的使用方法与第一个变体相同。

使用。它定义了一个
配对
收集器。
Map<Integer,DataPointSummary> coll = listeAllerPunkte.stream().collect(
    groupingBy(DataPoint::getId, Collector.of(
        DataPointSummary::new, DataPointSummary::add, DataPointSummary::merge)));
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()+']';
    }
}