Java 8 个 lambda 嵌套 Map
Java 8 lambdas nested Map
我正在尝试使用 Java-8 lambda 来解决以下问题:
给定一个 List<Transaction>
,对于每个 Category.minorCategory
,我需要每个 Category.minorCategory
的 Transaction.amount
和 Transaction.accountNumber
的 Map
的总和Transaction.amount
每 Transaction.accountNumber
的总和。根据下面的代码,我有这个工作。
我现在需要按 Category.majorCategory
分组,本质上是 returning a Map<String, Map<String, MinorCategorySummary>>
键控 Category.majorCategory
.
在按 Category.majorCategory
分组之前,我已经完成了所有工作,但很难看到解决方案;使用 lambda 进行编程的范式转变证明是一个陡峭的学习曲线。
TransactionBreakdown
是动作发生的地方,也是我想 return 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());
}
}
我觉得你的class设计很奇怪。为什么只将类别放入摘要 class 中,然后将类别作为映射键?如果有一个没有类别的摘要 class 会更有意义:
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()
)
));
我正在尝试使用 Java-8 lambda 来解决以下问题:
给定一个 List<Transaction>
,对于每个 Category.minorCategory
,我需要每个 Category.minorCategory
的 Transaction.amount
和 Transaction.accountNumber
的 Map
的总和Transaction.amount
每 Transaction.accountNumber
的总和。根据下面的代码,我有这个工作。
我现在需要按 Category.majorCategory
分组,本质上是 returning a Map<String, Map<String, MinorCategorySummary>>
键控 Category.majorCategory
.
在按 Category.majorCategory
分组之前,我已经完成了所有工作,但很难看到解决方案;使用 lambda 进行编程的范式转变证明是一个陡峭的学习曲线。
TransactionBreakdown
是动作发生的地方,也是我想 return 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());
}
}
我觉得你的class设计很奇怪。为什么只将类别放入摘要 class 中,然后将类别作为映射键?如果有一个没有类别的摘要 class 会更有意义:
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()
)
));