我可以在lambda表达式中跳过第一个流上的某些操作吗? 例如
List<BeanClass> fetch = getBeanClsss();
BeanClass bean = fetch.stream().reduce(newBean, (p1,p2)-> {
p1.setVal(p1.getVal() + p2.getVal());
// if first element skip
// else
p1.setValNum(p1.getValNum() + p2.getValNum());
return p1;
});
在第一个元素,我不想运行p1.setValNum方法而是运行p1.setVal方法。所以我想做除第一个以外的所有方法。
答案 0 :(得分:1)
不要使用reduce
进行可变缩减。如果流是并行的,您将得到不可预测的结果。您没有指定getVal
和getValNum
的返回类型,因此我认为它们都返回int
。如果你想澄清你的问题,我会相应地调整答案。
int sumVal = fetch.stream()
.mapToInt(BeanClass::getVal)
.sum();
int sumValNum = fetch.stream()
.skip(1) // now skipping the first one is straightforward!
.mapToInt(BeanClass::getValNum)
.sum();
newBean.setVal(newBean.getVal() + sumVal);
newBean.setValNum(newBean.getValNum() + sumValNum);
答案 1 :(得分:0)
答案 2 :(得分:0)
假设val和valNum是正数而且sum不会溢出:
如果我理解正确,那么比你第一次减少的时间要多,这比:p1 == newBean
。为了使reduce能够正常工作,您需要尊重identity property
,这意味着newBean
必须将val
和valNum
设置为zero
。
这意味着,如果您执行p1.getVal()
并看到它为零,则表示p2
实际上是您的信息流中的第一个元素。
另请注意,您在此处违反了reduce
- 您需要从reduce
方法返回一个新实例,例如:
.reduce(newBean, (p1, p2) -> {
BeanClass beanClass = new BeanClass();
// the first time you reduce
if(p1.getVal() == 0){
beanClass.setVal(p1.getVal() + p2.getVal());
}else {
beanClass.setVal(p1.getVal() + p2.getVal());
beanClass.setValNum(p1.getValNum() + p2.getValNum());
}
return beanClass;
})
最终你要做的是拥有一个BeanClass
实例,val
等于对来自Stream的所有其他val求和,除了第一个和{{ 1}}等于所有valNum的总和形成流。如果是这样,使用Misha's solution进行两次流式传输然后创建valNum
要简单得多。
答案 3 :(得分:0)
我假设您不打算在并行流中执行它(如果您这样做,请注意p1.setValNum(p1.getValNum() + p2.getValNum())
),这是StreamEx使用流利的setter的解决方案:代码是单独解释的。
StreamEx.of(fetch).mapFirst(b -> newBean.setVal(newBean.getVal() + b.getVal()))
.skip(1)
.reduce((a, b) -> a.setValNum(a.getValNum() + b.getValNum()));
使用流利的setter的BeanClass:
public static class BeanClass {
private int val;
private int valNum;
public int getVal() {
return val;
}
public BeanClass setVal(int val) {
this.val = val;
return this;
}
public int getValNum() {
return valNum;
}
public BeanClass setValNum(int valNum) {
this.valNum = valNum;
return this;
}
// ...
}