我想根据某个决定划分我的清单。我还有一张存储这些决定的地图。 目前我正在更新流本身的决定。我觉得这不是一个好习惯,因为我正在使用收集来做 除了计算分组标准之外的其他操作。我的另一个选择是再次浏览流 并使用forEach更新地图,但这意味着我将使用getFinalDecision两次。有更好的方法吗?有办法吗? 我可以在forEach中执行getFinalDecision并将其传递给groupingBy?
val test = myList.stream().collect(groupingBy(t -> {
A a = my_map.get(t.getSomething());
A finalDecision = getFinalDecision(t.getSomeOtherThing(), a);
my_map.put(t.getSomething(), finalDecision);
return finalDecision;
}));
答案 0 :(得分:3)
我不确定,但看起来你真正想做的更像是
Map<X,Y> result = myList.stream()
.collect(groupingBy(t -> t.getSomething(),
reducing(null, t -> t.getSomeOtherThing(), (a,b) -> getFinalDecision(b,a) )));
其中X
是getSomething()
的返回类型,Y
是getSomeOtherThing()
resp的返回类型。 getFinalDecision(…)
。当然,如果X
和Y
属于同一类型,它也可以使用。
这模仿原始代码中最初为空的映射的行为,导致null
作为第二个参数传递给getFinalDecision
,以便第一次出现每个不同的键。然后,第二个参数将是之前getFinalDecision
对该键的评估结果。
可能是旧代码的行为只是妥协,所以我会提到替代方案。当你使用
Map<X,Y> result = myList.stream()
.collect(groupingBy(t -> t.getSomething(), mapping(t -> t.getSomeOtherThing(),
collectingAndThen(reducing((a,b) -> getFinalDecision(a,b)), Optional::get))));
该值最初将是对每个不同密钥的第一个getSomeOtherThing()
调用的结果,并且只有在出现多个密钥时才会调用getFinalDecision
。因此,第二个参数不会是null
,除非getFinalDecision
本身在之前的评估中返回null
。
答案 1 :(得分:0)
您可以使用Map#compute来简化代码:
test = myList.stream().collect(groupingBy(t -> my_map.compute(t.getSomething()
,(it, a) -> getFinalDecision(t.getSomeOtherThing(), a))));
或使用Stream#peek&amp; Stream#collect描述它有两件事:合并&amp;&amp;的分组强>
test = myList.stream()
.map(it -> new SimpleEntry<>(it, getFinalDecision(it.getSomeOtherThing()
, my_map.get(it.getSomething()))))
.peek(it-> my_map.put(it.getKey(),it.getValue()))
.collect(groupingBy(SimpleEntry::getValue
,mapping(SimpleEntry::getKey, toList())));