java - 在 Map 上使用多个过滤器并使用 Java 8 不同地处理每个过滤器

标签 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))))));                                                                                          

这样我现在就可以得到如下的 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/

相关文章:

java - java中从文件中读取int

java - 如何摆脱Android应用栏中的后退按钮

python-2.7 - Python。属性错误 : 'NoneType' object has no attribute 'startswith'

java - 将 org.threeten.bp.* 和 org.joda.time* 转换为相应的 java.time.* 类的最佳方法

java - spring jms 全局 ErrorHandler 不工作

java - 在 apache POI 中自动换行 (Excel)

android - 如何将 Lambda 转换为简单的 Java 函数表达式

Java 8 - 如何通过 groupingBy 和 summingInt 使用 lambda 并使用按位运算符

java - Java 8 流中没有索引的原因是什么?

java - 如何使用 java lambda 流 :Given a list of students having books, 查找所有正在阅读最便宜书籍的学生