当前位置: 首页 > 知识库问答 >
问题:

合并两个流Java 8

华凯捷
2023-03-14

有没有办法把下面的2个状态结合起来呢?

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

我有一个类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之间的随机值。

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


共有1个答案

宰父保臣
2023-03-14

一般的解决方案是使用一个收集器,它可以组合两个收集器来同时处理这两个收集器。不幸的是,这样的收集器在标准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)));

如果点的坐标具有相同的大小,则上面的摘要实现很好地工作。如果在同一组中同时遇到非常大的值和非常小的值,则可能需要一个带有误差补偿的求和算法。我建议您不要自己实现它,而是使用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()+']';
    }
}

此变体的使用方式与第一个变体相同。

 类似资料:
  • 我有两个(或更多)

  • 我想将两个ObjectNode合并在一起,但要具有最佳的复杂性。我知道一种方法,我可以使用setAll方法,但它返回JsonNode,因此我必须转换它。我发现的转换过程的最佳方法是如何将JsonNode转换为ObjectNode。我认为这种转换一旦迭代Json,也许我们可以找到一个更好的解决方案。 我认为第二种方法是迭代第二个ObjectNode,然后用put方法一个接一个地添加到第一个Objec

  • 问题内容: 对于下面的输出,我需要做什么? 我调查了一下,但是正如javadoc所解释的,它只是一个接一个地追加,它不会交错/散布。 创建一个延迟串联的流,其元素是第一个流的所有元素,后跟第二个流的所有元素。 错误地给 如果我收集它们并进行迭代,但是希望获得更多Java8-y,Streamy :-),可以这样做 注意 我不想压缩流 “ zip”操作将从每个集合中获取一个元素并将其组合。 压缩操作的

  • 我需要做什么才能使输出如下所示? 我查看了concat,但正如javadoc所解释的,它只是一个接一个地附加,而不是交错/穿插。 创建一个延迟连接的流,其元素是第一个流的所有元素,然后是第二个流的所有元素。 错误地给予 如果我收集它们并迭代,可以做到这一点,但希望有更多的Java8-y,Streamy:-) 笔记 我不想让溪流断流 “zip”操作将从每个集合中获取一个元素并将其组合。 zip操作的

  • 问题内容: 我有两个像这样的数组: 我想结合这两个数组,使其不包含重复项,并保留其原始键。例如,输出应为: 我已经尝试过了,但是它正在更改其原始键: 有什么办法吗? 问题答案: 只需使用: 那应该解决。因为如果一个键出现多次(例如在您的示例中),则使用字符串键,因此一个键将覆盖具有相同名称的处理键。因为在您的情况下,它们两者都具有相同的值,但这无关紧要,并且还会删除重复项。 更新:我刚刚意识到,P

  • 问题内容: 我有两个键为s且值为的映射。给定两个s,合并它们的最简单方法是什么,如果两个键相同,则值是两个集合的并集。您可以假设值永远不会为null,并且如果有用的话,我们可以将它们设为s。 问题答案: 我们在谈论实例。在这种情况下,查找值为O(1),因此您只需获取一个映射,然后对该映射的条目进行迭代,看看另一个映射是否包含该键。如果没有,只需添加设置。如果包含密钥,则将两个集合并集(通过将一个集