我有一个订阅列表。订阅是具有频率和金额属性的类。我的目标是获得 TOTALACCRUEDMONTHLYAMOUNT,因此我分两步进行处理:1) 按频率对订阅进行分组,2) 将频率类型的金额按季度、半年和每年进行转换至每月。
例如:
Subscriptions [{
subscription {
frequency: Annually,
amount : 1200
},
subscription {
frequency: Annually,
amount : 1200
},
subscription {
frequency: Quarterly,
amount : 400
},
subscription {
frequency: Quarterly,
amount : 400
},
subscription {
frequency: Monthly,
amount : 100
},
subscription {
frequency: Semi Annually,
amount : 600
},
subscription {
frequency: Semi Annually,
amount : 600
}
}]
我能够使用以下逻辑进行分组
Map<String,BigDecimal> amountByFrequency = subscriptions.stream()
.collect(Collectors.groupingBy(
subscription::getFrequency,
Collectors.mapping(
Subscription::getAmount,
Collectors.reducing(
BigDecimal.ZERO,
(total,elm) ->(total.add(elm))))));
这样我现在就可以得到如下的 map
{[Monthly, 100],[Quarterly, 800],[Annually, 2400 ],[Semi Annually, 1200]}
但是,尚未将金额转换为每月金额,因此我使用下面的 switch 语句实现了这一点。
for(Map.Entry<String, BigDecimal> entry : amountByFrequency.entrySet()) {
switch(entry.getKey()) {
case "Monthly":
sum = sum.add(entry.getValue());
break;
case "Quaterly":
sum = sum.add(entry.getValue().divide(new BigDecimal("4"),2,RoundingMode.HALF_UP));
break;
case "Semiannually":
sum = sum.add(entry.getValue().divide(new BigDecimal("6"),2,RoundingMode.HALF_UP));
break;
case "Yearly":
case "Annually":
sum = sum.add(entry.getValue().divide(new BigDecimal("12"),2,RoundingMode.HALF_UP));
break;
}
}
有没有办法用Stream API替换上面的代码? 整个主类如下。
class Main {
public static void main(String[] args) {
List<Subscription> subscriptions = getSubscriptionsList();
BigDecimal sum = BigDecimal.ZERO;
//Group by frequency.
Map<String, BigDecimal> amountByFrequency = subscriptions.stream()
.collect(Collectors.groupingBy(Subscription::getFrequency, Collectors.mapping(Subscription::getAmount,
Collectors.reducing(BigDecimal.ZERO, (total, elm) -> (total.add(elm))))));
//convert amount to monthly
for (Map.Entry<String, BigDecimal> entry : amountByFrequency.entrySet()) {
switch (entry.getKey()) {
case "Monthly":
sum = sum.add(entry.getValue());
break;
case "Quaterly": // divide by 4, to convert to Monthly
sum = sum.add(entry.getValue().divide(new BigDecimal("4"), 2, RoundingMode.HALF_UP));
break;
case "Semiannually": // divide by 6, to convert to Monthly
sum = sum.add(entry.getValue().divide(new BigDecimal("6"), 2, RoundingMode.HALF_UP));
break;
case "Yearly":
case "Annually": // divide by 12, to convert to Monthly
sum = sum.add(entry.getValue().divide(new BigDecimal("12"), 2, RoundingMode.HALF_UP));
break;
}
}
System.out.println("java 8--" + sum); // accrued total subscription amount
}
static class Subscription {
private String frequency;
private BigDecimal amount;
public String getFrequency() {
return frequency;
}
public void setFrequency(String frequency) {
this.frequency = frequency;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
}
//build dummy subscription list.
public static List<Subscription> getSubscriptionsList() {
List<Subscription> SubscriptionsList = new ArrayList<>();
Subscription SubscriptionMonthly1 = new Subscription();
SubscriptionMonthly1.setFrequency("Monthly");
SubscriptionMonthly1.setAmount(new BigDecimal(1000.00));
Subscription SubscriptionMonthly2 = new Subscription();
SubscriptionMonthly2.setFrequency("Monthly");
SubscriptionMonthly2.setAmount(new BigDecimal(1000.00));
Subscription SubscriptionQuaterly1 = new Subscription();
SubscriptionQuaterly1.setFrequency("Quaterly");
SubscriptionQuaterly1.setAmount(new BigDecimal(1000.00));
Subscription SubscriptionQuaterly2 = new Subscription();
SubscriptionQuaterly2.setFrequency("Quaterly");
SubscriptionQuaterly2.setAmount(new BigDecimal(1000.00));
Subscription SubscriptionSemiannually1 = new Subscription();
SubscriptionSemiannually1.setFrequency("Semiannually");
SubscriptionSemiannually1.setAmount(new BigDecimal(1000.00));
Subscription SubscriptionSemiannually2 = new Subscription();
SubscriptionSemiannually2.setFrequency("Semiannually");
SubscriptionSemiannually2.setAmount(new BigDecimal(1000.00));
Subscription SubscriptionYearly1 = new Subscription();
SubscriptionYearly1.setFrequency("Yearly");
SubscriptionYearly1.setAmount(new BigDecimal(1000.00));
Subscription SubscriptionYearly2 = new Subscription();
SubscriptionYearly2.setFrequency("Yearly");
SubscriptionYearly2.setAmount(new BigDecimal(1000.00));
Subscription SubscriptionAnnually1 = new Subscription();
SubscriptionAnnually1.setFrequency("Annually");
SubscriptionAnnually1.setAmount(new BigDecimal(1000.00));
Subscription SubscriptionAnnually2 = new Subscription();
SubscriptionAnnually2.setFrequency("Annually");
SubscriptionAnnually2.setAmount(new BigDecimal(1000.00));
SubscriptionsList.add(SubscriptionMonthly1);
SubscriptionsList.add(SubscriptionMonthly2);
SubscriptionsList.add(SubscriptionQuaterly1);
SubscriptionsList.add(SubscriptionQuaterly2);
SubscriptionsList.add(SubscriptionSemiannually1);
SubscriptionsList.add(SubscriptionSemiannually2);
SubscriptionsList.add(SubscriptionYearly1);
SubscriptionsList.add(SubscriptionYearly2);
SubscriptionsList.add(SubscriptionAnnually1);
SubscriptionsList.add(SubscriptionAnnually2);
return SubscriptionsList;
}
}
最佳答案
你可以使用类似的东西:
private static Map<String,Double> frequencyFactor = new HashMap<>();
frequencyFactor.add("Monthly", 1);
frequencyFactor.add("Annualy", 1.0/12);
frequencyFactor.add("Yearly", 1.0/12);
frequencyFactor.add("Quaterly", 1.0/4);
frequencyFactor.add("Semiannually", 1.0/6);
Integer sum = subs.stream()
.mapToDouble(sub -> sub.getAmount() * frequencyFactor.get(sub.getFrequency()))
.sum();
关于java - 在 Map 上使用多个过滤器并使用 Java 8 不同地处理每个过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43987085/