首页 > 解决方案 > 将项目收集到括号中(当前组和所有先前组)

问题描述

(抱歉,如果“括号”一词令人困惑,我将其取自荷兰语翻译的“税级”)。

如何根据属性阈值将项目收集到组和每个前面的组中?

例子:

Loan A, duration of 6 months
Loan B, duration of 10 months
Loan C, duration of 12 months

结果为Map<Integer, List<Loan>>

6 -> {A, B, C}
10 -> {B, C}
12 -> {C}

目前我正在使用 LinkedHashMap 路线,然后在从流中收集项目后,遍历所有组以更新它们:

Map<Integer, List<Loan>> loansByDuration = loans.stream()
        .collect(groupingBy(Loan::getDuration, LinkedHashMap::new, toList()));

List<Loan> previousGroup = null;
for (List<Loan> currentGroup : loansByDuration.values()) {
    if (previousGroup != null) {
        currentGroup.addAll(previousGroup);
    }
    previousGroup = currentGroup;
}

所以我正在做的是地图中的每个后续列表值都将包含所有以前的贷款加上仅与相应的持续时间键相关的贷款。类似于累积小计。

这可以通过标准 API 或自定义收集器之类的东西来完成吗?

标签: javajava-streamcollectors

解决方案


对于用例,是否有必要使用类似的类型Map<Integer, List<Loan>>?因此,每个列表都将包含所有以前的贷款。这意味着会有对Loan.

或者是提供关于loans分组的视图的用例duration
在这种情况下,我们可以使用另一种方法:贷款视图使用Stream(基于 Java 9+)。

public class Loans {

    private final List<Loan> loans;

    public Loans(List<Loan> loans) {
        this.loans = loans.stream()
                .sorted(Comparator.comparingInt(Loan::getDuration))
                .collect(Collectors.toList());
    }

    public Stream<Loan> getUpTo(int duration) {
        return loans.stream().takeWhile(l -> l.getDuration() <= duration);
    }

}

由于我们有 a List<Loan>sorted by,duration我们可以使用Stream.takeWhilea 来获取某个sStream的所需Loans duration

这可以像这样工作:

Loans loans = new Loans(List.of(new Loan("A", 6), new Loan("B", 10), new Loan("C", 12));
loans.getUpTo(1); // <empty>
loans.getUpTo(5); // <empty>
loans.getUpTo(6); // Loan("A", 6)
loans.getUpTo(10); // Loan("A", 6), new Loan("B", 10)
loans.getUpTo(11); // Loan("A", 6), new Loan("B", 10)
loans.getUpTo(12); // Loan("A", 6), new Loan("B", 10), Loan("C", 12)
loans.getUpTo(100); // Loan("A", 6), new Loan("B", 10), Loan("C", 12)

如果List<Loan>需要 a ,我们仍然可以collect使用流式元素toList()


推荐阅读