我可以在reduce操作中对lambda表达式设置一个条件吗?

时间:2017-09-22 07:04:12

标签: lambda java-8 java-stream

我可以在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方法。所以我想做除第一个以外的所有方法。

4 个答案:

答案 0 :(得分:1)

不要使用reduce进行可变缩减。如果流是并行的,您将得到不可预测的结果。您没有指定getValgetValNum的返回类型,因此我认为它们都返回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)

您可以0使用Stream作为:

skip()
  

返回由此流的其余元素组成的流   在丢弃流的前n个元素之后。如果这个流   包含少于n个元素,然后将返回一个空流。

答案 2 :(得分:0)

假设val和valNum是正数而且sum不会溢出

如果我理解正确,那么比你第一次减少的时间要多,这比:p1 == newBean。为了使reduce能够正常工作,您需要尊重identity property,这意味着newBean必须将valvalNum设置为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;
    }
    // ...
}