2

次の問題を解決するためにJava-8ラムダを使用しようとしています:

a が与えられたList<Transaction>場合、それぞれについて、 perの合計とperのCategory.minorCategory合計が必要です。以下のコードに従って、これが機能しています。でグループ化する必要があり、基本的にキー付きの を返します。Transaction.amountCategory.minorCategoryMapTransaction.accountNumberTransaction.amountTransaction.accountNumberCategory.majorCategoryMap<String, Map<String, MinorCategorySummary>>Category.majorCategory

グループ化の段階まですべてが機能していますCategory.majorCategoryが、解決策を見るのに苦労しています。ラムダを使用したプログラミングのパラダイム シフトは、学習曲線が急勾配であることを証明しています。

TransactionBreakdownアクションが発生する場所であり、 を返したい場所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());
    }

}
4

1 に答える 1

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
}

これで、2 つの問題が明確に解決され、冗長性がなくなりました。

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()
                )
        ));
于 2015-06-13T23:43:19.950 に答える