在Map上使用多个过滤器并使用Java 8

时间:2017-05-15 19:09:44

标签: java lambda java-8 java-stream

我有一份订阅列表。订阅是具有频率和金额属性的类。我的目标是获得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))))));                                                                                          

这样我就可以获得现在的地图了

{[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;

}

}

2 个答案:

答案 0 :(得分:3)

你可以沿着这些方向使用:

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();

答案 1 :(得分:2)

根据Aaron的建议,我能够使用流将以下行替换为switch语句。

Map<String,BigDecimal> frequencyFactor = new HashMap<>();
frequencyFactor.put("Monthly", new BigDecimal(1.0));
frequencyFactor.put("Annually", new BigDecimal(1.0/12));
frequencyFactor.put("Yearly", new BigDecimal(1.0/12));
frequencyFactor.put("Quaterly", new BigDecimal(1.0/4));
frequencyFactor.put("Semiannually", new BigDecimal(1.0/6));

amountByFrequency.replaceAll((k,v) -> v .multiply(frequencyFactor.get(k)));
BigDecimal sum = amountByFrequency.entrySet().stream().map(Map.Entry::getValue).reduce(BigDecimal.ZERO, BigDecimal::add ).setScale(2, RoundingMode.HALF_UP);
System.out.println(amountByFrequency);