我认为 Java8 中没有任何新内容可以真正帮助解决这个问题,至少效率不高。
如果您仔细查看所有新 API,您会发现它们中的大多数旨在提供更强大的原语来处理单个值及其序列 - 即,处理序列double
, int
, ? extends Object
, etc.
例如,计算序列的平均值double
,JDK引入了一个新类——DoubleSummaryStatistics
它做了一件显而易见的事情 - 收集任意序列的摘要double
价值观。
我实际上建议你自己采取类似的方法:制作你自己的StatsSummary
类看起来像这样:
// assuming this is what your Stats class look like:
class Stats {
public final double a ,b; //the two stats
public Stats(double a, double b) {
this.a = a; this.b = b;
}
}
// summary will go along the lines of:
class StatsSummary implements Consumer<Stats> {
DoubleSummaryStatistics a, b; // summary of stats collected so far
StatsSummary() {
a = new DoubleSummaryStatistics();
b = new DoubleSummaryStatistics();
}
// this is how we collect it:
@Override public void accept(Stats stat) {
a.accept(stat.a); b.accept(stat.b);
}
public void combine(StatsSummary other) {
a.combine(other.a); b.combine(other.b);
}
// now for actual methods that return stuff. I will implement only average and min
// but rest of them are not hard
public Stats average() {
return new Stats(a.getAverage(), b.getAverage());
}
public Stats min() {
return new Stats(a.getMin(), b.getMin());
}
}
现在,上述实现实际上允许您在使用时表达正确的意图Stream
等等:通过构建严格的 API 并使用 JDK 中可用的类作为构建块,总体上会减少错误。
但是,如果您只想在某个地方计算一次平均值并且不需要其他任何东西,则对此类进行编码有点矫枉过正,这里有一个快速而肮脏的解决方案:
Map<String, Stats> computeAverage(Map<String, List<Stats>> statsByPosition) {
Map<String, Stats> averaged = new HashMap<>();
statsByPosition.forEach((position, statsList) -> {
averaged.put(position, averageStats(statsList));
});
return averaged;
}
Stats averageStats(Collection<Stats> stats) {
double a, b;
int len = stats.size();
for(Stats stat : stats) {
a += stat.a;
b += stat.b;
}
return len == 0d? new Stats(0,0) : new Stats(a/len, b/len);
}