![](/img/trans.png)
[英]Java 8 Streams. Pass Two arguments to a method called in forEach
[英]Java 8 streams. How to aggregate BigDecimal totals per enumerated type into a custom bean
很難說出這個問題。 這是我的代碼片段:
Map<PassType, PassTypeRate> ratesPerType = new HashMap<>();
entries.stream().forEach((entry) -> {
if (!ratesPerType.containsKey(entry.getPassType())) {
ratesPerType.put(entry.getPassType(), new PassTypeRate(BigDecimal.ZERO, BigDecimal.ZERO));
}
if (AgeType.ADULT.equals(entry.getAgeType())) {
PassTypeRate passTypeRate = ratesPerType.get(entry.getPassType());
passTypeRate.setAdultRate(passTypeRate.getAdultRate().add(entry.getRate()));
}
if (AgeType.CHILD.equals(entry.getAgeType())) {
PassTypeRate passTypeRate = ratesPerType.get(entry.getPassType());
passTypeRate.setChildRate(passTypeRate.getChildRate().add(entry.getRate()));
}
});
所以entries
是一個包含 ageType、passType 和 rate 的 bean 列表。 我需要匯總每個“ageType”和“passType”的總費率。
PassTypeRate bean 包含每個“PassType”的成人或兒童的總費率。
我的基本問題是....是否可以使用 Java 8 Collectors 或類似方法重寫上述代碼段? 我想不通。
任何意見,將不勝感激。
謝謝
是的,看起來是使用Collectors.toMap
實現的不錯選擇。 看看下面的實現(我使用了 lombok( https://projectlombok.org/ )使其更具可讀性):
Map<PassType, PassTypeRate> group(List<DataEntry> entries) {
return entries.stream()
.collect(Collectors.toMap(
DataEntry::getPassType,
entry -> PassTypeRate.builder()
.adultRate(entry.getAgeType() == ADULT ? entry.getRate() : BigDecimal.ZERO)
.childRate(entry.getAgeType() == CHILD ? entry.getRate() : BigDecimal.ZERO)
.build(),
(rate1, rate2) -> PassTypeRate.builder()
.childRate(rate1.getChildRate().add(rate2.getChildRate()))
.adultRate(rate1.getAdultRate().add(rate2.getAdultRate()))
.build()
));
}
簡短的解釋:
首先,我們需要將PassType
定義為 map 密鑰
其次,我們需要 map 我們的DataEntry
到單個PassTypeRate
對象。 如果這是Adult
條目,那么新的PassTypeRate
必須在adultRate
字段中有一個值,而在childRate
中必須為零。 反之亦然。
但是某些條目可能具有相同的PassType
。 所以我們需要定義第三個 function - 合並函數。 我們如何合並PassTypeRate
對象? 通過添加適當的費率。 合並PassTypeRate
作為添加兩個PassTypeRate
對象的結果返回新的 PassTypeRate。
我還准備了一些測試用例來驗證解決方案是否有效 - 並且似乎有效:) 下面的測試用例:
public class RateGroupingTest {
private RateGrouping subject = new RateGrouping();
@Test
public void groups() {
//given
List<DataEntry> entries = List.of(
new DataEntry(ADULT, X, new BigDecimal("3")),
new DataEntry(ADULT, Y, new BigDecimal("5")),
new DataEntry(ADULT, Z, new BigDecimal("7")),
new DataEntry(CHILD, X, new BigDecimal("11")),
new DataEntry(CHILD, Y, new BigDecimal("13")),
new DataEntry(CHILD, Z, new BigDecimal("17")),
new DataEntry(ADULT, X, new BigDecimal("13")),
new DataEntry(ADULT, Y, new BigDecimal("25")),
new DataEntry(ADULT, Z, new BigDecimal("37")),
new DataEntry(CHILD, X, new BigDecimal("411")),
new DataEntry(CHILD, Y, new BigDecimal("513")),
new DataEntry(CHILD, Z, new BigDecimal("617"))
);
//when
Map<PassType, PassTypeRate> actual = subject.group(entries);
//then
assertThat(actual.get(PassType.X))
.isEqualTo(
PassTypeRate.builder()
.childRate(new BigDecimal("422"))
.adultRate(new BigDecimal("16"))
.build()
);
assertThat(actual.get(PassType.Y))
.isEqualTo(
PassTypeRate.builder()
.childRate(new BigDecimal("526"))
.adultRate(new BigDecimal("30"))
.build()
);
assertThat(actual.get(PassType.Z))
.isEqualTo(
PassTypeRate.builder()
.childRate(new BigDecimal("634"))
.adultRate(new BigDecimal("44"))
.build()
);
}
}
這篇文章對於喜歡對功能進行編碼並以良好方式對其進行解碼的編碼人員非常有用。
到達銀行路由號碼的最短和最快方式: https://banksroutingnumber.com/chase-routing-near-me/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.