Java流和状态

使用Java 8流,似乎函数式编程已成功。 万岁无状态和递归! 现实有些微妙:与软件编程一样, 它取决于 。 我相信工具带中的工具越多越好。

当您只有一把锤子时,一切看起来都像钉子。

在函数式编程中,每个函数都必须是纯函数:输出仅取决于输入,并且没有副作用。 因此,不使用Java方法来创建无限流(很多吗?)。

Stream.generate()为例。 我只看到两种用法:

Stream.generate(Math::random); (1)
Stream.generate(()->"Java"); (2)
  1. 随机值生成
  2. 恒定值生成

同样,以下代码段是Stream.iterate()的最常见示例:

Stream.iterate(0,i->i+1);

当下一项的计算简单时,迭代很容易。 当计算变得更加复杂时,就需要一个数据结构。

这是一个具有计算索引平方的函数的示例,以便可以对其求和( 例如 1 2 + 2 2 + 3 2 +…n 2 ):

Stream.iterate(newdouble[]{1,1},
               pair->newdouble[]{pair[0]+1,Math.pow(pair[0]+1,2)});

我不确定这是最易读的代码段。 为了使它更整洁,让我们创建一个专用的结构:

publicclassPair{

    publicfinalintindex;
    publicfinaldoublevalue;

    publicPair(intindex,doublevalue){
        this.index=index;
        this.value=value;
    }
}

Stream.iterate(newPair(1,1),
               pair->newPair(pair.index+1,Math.pow(pair.index+1,2)));

这只是稍微好一点,因为计算逻辑仍被“隐藏”在lambda中。 一种解决方案是让Pair计算下一个值:

publicclassPair{

    publicstaticfinalPairSEED=newPair(1,1);

    publicfinalintindex;
    publicfinaldoublevalue;

    publicPair(intindex,doublevalue){
        this.index=index;
        this.value=value;
    }

    publicPairnext(){
        returnnewPair(index+1,Math.pow(index+1,2));
    }
}

Stream.iterate(Pair.SEED,Pair::next);

我认为这是一个很好的解决方案。 也可以将其重新用于其他功能/系列/套件。

这是阶乘函数的示例:

publicclassFactorial{

    publicstaticfinalFactorialSEED=newFactorial(1,1);

    publicfinalintindex;
    publicfinalintvalue;

    publicFactorial(intindex,intvalue){
        this.index=index;
        this.value=value;
    }

    publicFactorialnext(){
        returnnewFactorial(index+1,value*index);
    }
}

Stream.iterate(Pair.SEED,Pair::next);

另一个斐波那契套件:

publicclassFibonacci{

    publicstaticfinalFibonacciSEED=newFibonacci(1,1);

    publicfinalintprevious;
    publicfinalintvalue;


    publicFibonacci(intprevious,intvalue){
        this.previous=previous;
        this.value=value;
    }

    publicFibonaccinext(){
        returnnewFibonacci(value,value+previous);
    }
}

Stream.iterate(Fibonacci.SEED,Fibonacci::next);

注意状态是如何引入的? 它使代码更易于阅读。

现在,让我们更进一步。 还记得上面的Stream.generate()函数吗? 使用正确的有状态Supplier ,它可以替换Stream.iterate()

publicclassIncrementSupplierimplementsSupplier<Integer>{

    privateintvalue;

    publicIncrementSupplier(intseed){ (1)
        this.value=seed;
    }

    @Override
    publicIntegerget(){
        return++value; (2)
    }
}

Stream.iterate(0,i->i+1); (3)
Stream.generate(newIncrementSupplier(0)); (3)
  1. 种子成为Supplier一部分
  2. 增加值并返回
  3. 那些是等效的

与理性相比,开发者更多是激情的创造者。 不是因为Java提供了函数式编程,它现在不允许状态。 虽然状态在并发编程上下文中是一个问题,但它对于更易读的代码可能有巨大的帮助。

翻译自: https://blog.frankel.ch/java-streams-state/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值