[英]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
是一個包含大量DataPoints
的List
現在,我想創建一個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.