将项目收集到括号中(当前组和所有前面的组)



(抱歉,如果术语"括号"令人困惑,我从荷兰语翻译的"税括号"中取了它(。

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

例:

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 或自定义收集器之类的东西来完成吗?

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

还是按duration分组提供loans视图的用例?
在这种情况下,我们可以使用另一种方法:使用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);
}
}

由于我们有一个按duration排序的List<Loan>,因此我们可以使用Stream.takeWhile来获取特定duration所需LoanStream

例如,这是有效的:

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>,我们仍然可以collect流元素toList().

我能想到的简单解决方案是这样的

class Bucket(int limit, List<Loan> elements)
List<Int> buckets = Arrays.asList(6, 10, 12); // The bucket that you want to put items into
buckets.stream.flatMap(bucketLimit -> {
List<Loan> loans = loans.stream()
.filter(l -> l.getDuration() <= bucket)
.collect(Collectors.toList());
return new Bucket(bucketLimit, loans);
})
.collect(Collectors.toMap(Bucket::limit, Bucket::loans))

这里可能存在一些语法错误,但您应该能够执行类似操作。

最新更新