Java 8 lambdas嵌套Map

时间:2015-06-13 20:24:53

标签: java lambda java-8 java-stream collectors

我正在尝试使用Java-8 lambdas来解决以下问题:

给定List<Transaction>,对于每个Category.minorCategory,我需要Transaction.amountCategory.minorCategoryMap Transaction.accountNumber的总和。每Transaction.amount Transaction.accountNumber。根据下面的代码,我有这个工作。 我现在需要按Category.majorCategory分组,基本上返回Map<String, Map<String, MinorCategorySummary>> Category.majorCategory上的Category.majorCategory

我有一切工作直到TransactionBreakdown分组的阶段,但很难看到解决方案;用lambdas编程的范式转换证明了一个陡峭的学习曲线。

Map<String, Map<String, MinorCategorySummary>>是行动发生的地方,也是我想要返回public class Transaction { private final String accountNumber; private final BigDecimal amount; private final Category category; } public class Category { private final String majorCategory; private final String minorCategory; } public class MinorCategorySummary { private final BigDecimal sumOfAmountPerMinorCategory; private final Map<String, BigDecimal> accountNumberSumOfAmountMap; private final Category category; } public class TransactionBreakdown { Function<Entry<String, List<Transaction>>, MinorCategorySummary> transactionSummariser = new TransactionSummariser(); public Map<Object, MinorCategorySummary> getTransactionSummaries(List<Transaction> transactions) { return transactions .stream() .collect(groupingBy(t -> t.getCategory().getMinorCategory())) .entrySet() .stream() .collect( toMap(Entry::getKey, transactionSummariser)); } } public class TransactionSummariser implements Function<Entry<String, List<Transaction>>, MinorCategorySummary> { @Override public MinorCategorySummary apply( Entry<String, List<Transaction>> entry) { return new MinorCategorySummary( entry.getValue() .stream() .map(Transaction::getAmount) .collect(reducing(BigDecimal.ZERO, BigDecimal::add)), entry.getValue() .stream() .collect( groupingBy(Transaction::getAccountNumber, mapping(Transaction::getAmount, reducing(BigDecimal.ZERO, BigDecimal::add)))), entry.getValue().get(0).getCategory()); } } 的地方。

re.sub

1 个答案:

答案 0 :(得分:5)

你的班级设计对我来说很奇怪。为什么将类别放入摘要类只是为了将类别作为映射键?有一个没有类别的摘要类会更有意义:

public class TransactionSummary {

    private final BigDecimal amount;
    private final Map<String, BigDecimal> acctToTotal;

    TransactionSummary(Map<String, BigDecimal> acctToTotal) {
        this.acctToTotal = Collections.unmodifiableMap(acctToTotal);
        this.amount = acctToTotal.values().stream()
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    public static Collector<Transaction, ?, TransactionSummary> collector() {
        // this can be a static constant
        return collectingAndThen(
            toMap(Transaction::getAccountNumber,Transaction::getAmount,BigDecimal::add),
            TransactionSummary::new
        );
    }

    // getters
}

现在你的两个问题已经清楚地解决了,没有冗余:

Map<String, TransactionSummary> minorSummary = transactions.stream()
        .collect(groupingBy(
                t -> t.getCategory().getMinorCategory(),
                TransactionSummary.collector()
        ));

Map<String, Map<String, TransactionSummary>> majorMinorSummary = transactions.stream()
        .collect(groupingBy(
                t -> t.getCategory().getMajorCategory(),
                groupingBy(
                        t -> t.getCategory().getMinorCategory(),
                        TransactionSummary.collector()
                )
        ));