この回答は、同様の操作を行うJDKの方法に触発されています。つまり、私はDoubleSummaryStatisticsクラスを参照しています。
まず、我々は我々が収集されますのBigDecimalの詳細については、ホルダーを定義します。
public class BigDecimalSummaryStats {
private long count;
private MathContext mc;
private BigDecimal sum = BigDecimal.ZERO;
private BigDecimal max;
private BigDecimal min;
public BigDecimalSummaryStats(MathContext mathCtx) {
mc = requireNonNull(mathCtx);
}
public Supplier<BigDecimalSummaryStats> supplier(MathContext ctx) {
return() -> new BigDecimalSummaryStats(ctx);
}
public void accept(BigDecimal value) {
requireNonNull(value);
count++;
sum = sum.add(value, mc);
min = min.min(value);
max = max.max(value);
}
public void combine(BigDecimalSummaryStats other) {
requireNonNull(other);
count += other.count;
sum = sum.add(other.sum, mc);
min = min.min(other.min);
max = max.max(other.max);
}
public long getCount() {
return count;
}
public BigDecimal getSum() {
return sum;
}
public BigDecimal getMax() {
return max;
}
public BigDecimal getMin() {
return min;
}
public BigDecimal getAverage() {
long c = getCount();
return c == 0 ? BigDecimal.ZERO : getSum().divide(BigDecimal.valueOf(c), mc);
}
}
これは、BigDecimalの値の任意のシーケンスからの要約を収集するのに適した素敵な一般的なユーティリティを提供します。
その後、我々はアイテムの概要クラスを定義することができます
public class ItemSummaryStats {
private BigDecimalSummaryStats value1;
private BigDecimalSummaryStats value2;
private BigDecimalSummaryStats value3;
// ... other fields as needed
public ItemSummaryStats(MathContext math) {
value1 = new BigDecimalSummaryStats(math);
value2 = new BigDecimalSummaryStats(math);
value3 = new BigDecimalSummaryStats(math);
}
public void accept(Item item) {
value1.accept(item.value1);
value2.accept(item.value2);
value3.accept(item.value3);
// ... other fields as needed
}
public void combine(ItemSummaryStats other) {
value1.combine(other.value1);
value2.combine(other.value2);
value3.combine(other.value3);
}
public TotalItem get(
Function<BigDecimalSummaryStats, BigDecimal> v1Mapper,
Function<BigDecimalSummaryStats, BigDecimal> v2Mapper,
Function<BigDecimalSummaryStats, BigDecimal> v3Mapper) {
TotalItem t = new TotalItem();
t.value1 = v1Mapper.get(value1);
t.value2 = v2Mapper.get(value2);
t.value3 = v3Mapper.get(value3);
return t;
}
public TotalItem getSum() {
return get(BigDecimalSummaryStats::getSum,
BigDecimalSummaryStats::getSum,
BigDecimalSummaryStats::getSum);
}
public TotalItem getAverage() {
return get(BigDecimalSummaryStats::getAverage,
BigDecimalSummaryStats::getAverage,
BigDecimalSummaryStats::getAverage);
}
public TotalItem getMin() {
return get(BigDecimalSummaryStats::getMin,
BigDecimalSummaryStats::getMin,
BigDecimalSummaryStats::getMin);
}
//.... other methods basically all the same. You get the idea.
}
そして最後に、我々はこのように、この良さを使用します。このアプローチの
TotalItem totals = list.stream().collect(
Collector.of(() -> new ItemStatsSummary(MathContext.DECIMAL64),
ItemStatsSummary::accept,
ItemStatsSummary::combine,
ItemStatsSummary::getSum)
)
短所:
- をアドホックなソリューションよりも開発時間がやや長くなります。
はるかに賛否を上回る、または少なくとも私はそれを確信しています:
- は原則関心事の分離に従う:アイテムの統計は、特定のフィールドの要約を収集する方法実際に心配はありません。彼らBigDecimalSummaryが動作すると信じることができます
- テスト可能:各部分は、それぞれのスイートでテストすることができます。同じAPIを使用しているため、すべてのフィールドが同じように動作することを信頼できます。
- フレキシブル:
get(Function...)
メソッドは、可能性の大きなリストを公開しています。必要に応じて、最初のフィールドの合計、2番目の平均と3番目の最小値を収集できます。
統計情報の新しいクラスを作成する必要があります。 –
結果ごとに3つの合計値、または同じ合計に3つの異なる値を意味する、それぞれの値は個別にですか? – appl3r