With Java 8 streams, it seems Functional Programming has won. Long live statelessness and recursion! Reality is a bit more nuanced: as always in software programming, it depends. I believe that the more tools in your toolbelt, the better it is.

When all you have is a hammer, everything looks like a nail.

In Functional Programming, every function needs to be pure: output only depends on input, and there are no side-effects. For this reason, Java methods to create infinite streams are not used (much?).

Take for example Stream.generate() . I’ve seen only two usages:

Stream . generate ( Math: : random ); (1) Stream . generate (() -> "Java" ); (2)

1 Random value generation 2 Constant value generation

Likewise, the following snippet is the most common example of Stream.iterate() :

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

Iteration is easy when the computation of the next term is simple. A data structure is required when the computation becomes more complex.

Here’s an example with a function that computes the square of the index, so that it can be summed afterwards (e.g. 12 + 22 + 32 + …​ n2):

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

I’m not sure this is the most readable code snippet. To make it cleaner, let’s create a dedicated structure:

public class Pair { public final int index ; public final double value ; public Pair ( int index , double value ) { this . index = index ; this . value = value ; } } Stream . iterate ( new Pair ( 1 , 1 ), pair -> new Pair ( pair . index + 1 , Math . pow ( pair . index + 1 , 2 )));

This is only marginally better, as the computation logic is still "hidden" in the lambda. One solution could be to let the Pair compute the next value:

public class Pair { public static final Pair SEED = new Pair ( 1 , 1 ); public final int index ; public final double value ; public Pair ( int index , double value ) { this . index = index ; this . value = value ; } public Pair next () { return new Pair ( index + 1 , Math . pow ( index + 1 , 2 )); } } Stream . iterate ( Pair . SEED , Pair: : next );

I think this is a pretty neat solution. It can be re-used for other functions/series/suites as well.

Here’s an example for the factorial function:

public class Factorial { public static final Factorial SEED = new Factorial ( 1 , 1 ); public final int index ; public final int value ; public Factorial ( int index , int value ) { this . index = index ; this . value = value ; } public Factorial next () { return new Factorial ( index + 1 , value * index ); } } Stream . iterate ( Pair . SEED , Pair: : next );

And another one for the Fibonacci suite:

public class Fibonacci { public static final Fibonacci SEED = new Fibonacci ( 1 , 1 ); public final int previous ; public final int value ; public Fibonacci ( int previous , int value ) { this . previous = previous ; this . value = value ; } public Fibonacci next () { return new Fibonacci ( value , value + previous ); } } Stream . iterate ( Fibonacci . SEED , Fibonacci: : next );

Notice how state was introduced? It made the code easier to read.

Now, let’s push the things a bit further. Remember the Stream.generate() function above? With the correct stateful Supplier , it can replace Stream.iterate() :

public class IncrementSupplier implements Supplier < Integer > { private int value ; public IncrementSupplier ( int seed ) { (1) this . value = seed ; } @Override public Integer get () { return ++ value ; (2) } } Stream . iterate ( 0 , i -> i + 1 ); (3) Stream . generate ( new IncrementSupplier ( 0 )); (3)

1 The seed becomes part of the Supplier 2 Increment the value and return it 3 Those are equivalent