使用 Java 8 Stream Reduce 在使用先前元素值对每个元素执行操作后返回 List

2024-01-29

我是 Streams 和 Reduce 的新手,所以我正在尝试它并遇到了一个问题:

我有一个计数器列表,其中有开始计数器和结束计数器。一个项目的起始计数器始终是前一个项目的结束计数器。我有这些计数器的列表listItems我想有效地循环遍历,过滤掉不活动的记录,然后将列表减少到设置所有 StartCounters 的新列表中。我有以下代码:

List<CounterChain> active = listItems.stream()
                .filter(e -> e.getCounterStatus() == CounterStatus.ACTIVE)
                .reduce(new ArrayList<CounterChain>(), (a,b) -> { b.setStartCounter(a.getEndCounter()); return b; });

但它并没有真正起作用,我有点卡住了,有人能给我一些建议来帮助我让它工作吗?或者是否有同样有效的更好方法来做到这一点?谢谢!


A 减少将所有元素减少为单个值。使用减少函数(a,b) -> bform 会将所有元素减少到最后一个,所以当你想要得到一个时,它是不合适的List包含所有(匹配的)元素。

除此之外,您正在对输入值进行修改,这违反了该操作的约定。进一步注意,该函数需要是联想性的, 是。流是否会执行并不重要f(f(e₁,e₂),e₃)) or f(e₁,f(e₂,e₃))使用归约函数处理三个后续流元素时。

或者,简而言之,您没有使用适合这项工作的正确工具。

最干净的解决方案是不要混合这些不相关的操作:

List<CounterChain> active = listItems.stream()
    .filter(e -> e.getCounterStatus() == CounterStatus.ACTIVE)
    .collect(Collectors.toList());
for(int ix=1, num=active.size(); ix<num; ix++)
    active.get(ix).setStartCounter(active.get(ix-1).getEndCounter());

第二个循环也可以使用来实现forEach,但由于其有状态的性质,它需要一个内部类:

active.forEach(new Consumer<CounterChain>() {
    CounterChain last;
    public void accept(CounterChain next) {
        if(last!=null) next.setStartCounter(last.getEndCounter());
        last = next;
    }
});

或者,使用基于索引的流:

IntStream.range(1, active.size())
    .forEach(ix -> active.get(ix).setStartCounter(active.get(ix-1).getEndCounter()));

但与普通的相比,两者都没有太大优势for loop.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Java 8 Stream Reduce 在使用先前元素值对每个元素执行操作后返回 List 的相关文章

随机推荐