Java streams and Fibonacci
Tags: java, fibonacci, streams, code
Published: 2021-04-03 21:20:12

So, you still struggling trying to understand expressions like this in Java 8+:

```
Stream.iterate(new long[]{ 0L, 1L }, p->new long[]{ p[1], p[0]+p[1] }).map(p -> p[0]).limit(10).map(p->p+" ").forEach(System.out::print);
```

Do you have a clue about what this line is about to do, when you hit Run? Yes, you're right, you'll have the Fibonacci sequence of 10 elements printed in your console, like this:

```
0 1 1 2 3 5 8 13 21 34
```

It's a tricky one, and if you didn't answer that correctly, I'll try something easier before digging into an explanation.

So, your second chance is right here:
```
Arrays.asList(1, 2, 2, 3, 4, 4, 4, 5, 6, 8).stream()
    .distinct()
    .filter(x -> x % 2 == 0)
    .map(x -> x * 10)
    .skip(1)
    .limit(2)
    .peek(System.out::println)
    .reduce(0, Integer::sum)
```

Don't need no math right now, because what I wanted to show you is how this works step by step. 

So, first of all, what a *STREAM* is?

Must have in mind is that:
* Streams are **not** a data structure
* Streams doesn't store or modify data
* It can be defined as a **wrapper** around a data source
* Supports functional-style operations
* Fast and convenient bulk processing over a data source
* Iteration over elements are sequential and declarative
* Parallel-friendly, immutable and thread-safe
* Lazy evaluation
* Single use
* Don't confuse with Java I/O (ex. FileInputStream)

Besides that, we have:
* Intermediate operations: stream chained operations that return new streams (pipeline)
* Terminal operations: execute the stream and produces a non-stream object (result)

You can create a stream by invoking the methods `stream()` or `parallelStream()`, or even use `Stream.of`, `Stream.ofNullable` or `Stream.iterate` (like I did for Fibonacci).

Let's try to get back a little bit and "debug" the easy example up there:

```
Arrays.asList(1, 2, 2, 3, 4, 4, 4, 5, 6, 8)
```

Creates a new Collection, so we can iterate through its elements via stream

```
.stream()
```

Starts a new stream

```
.distinct()
```

Retain distinct elements, returning: `[1, 2, 3, 4, 5, 6, 8]`

```
.filter(x -> x % 2 == 0)
```

Filter pair elements by applying mod 2, returning: `[2, 4, 6, 8]`

```
.map(x -> x * 10)
```

Multiplicates each filtered element by 10, returning: `[20, 40, 60, 80]`

```
.skip(1)
```

Skips the first element of the sequence, returning: `[40, 60, 80]`

```
.limit(2)
```

Returns the first 2 elements of the sequence: `[40, 60]`
This is a "short-circuit" command, i.e., it'll interrupt the stream processing when the condition is match - in this case, when we reach the second element

```
.peek(System.out::println)
```

Some kind of "debug" mode of stream, in this case it'll `println` each remaining element of the stream operation: `40` and `60`

```
.reduce(0, Integer::sum)
```

In this case, we're gonna effectively consume the stream and get a Integer result from it: the sum of all elements, where `0` is the starting value, and `Integer::sum` invokes the `Integer.sum(int a, int b)` function from the Integer class, that will be performed over each remaining element from the stream operation, that is, 40 and 60, then resulting **100**.

Now, what about the Fibonacci stuff up there? Right on, let's get back to it.

```
Stream.iterate
```

By definition, we have: 

> Returns an infinite sequential ordered Stream produced by iterative application of a function f to an initial element seed, producing a Stream consisting of seed, f(seed), f(f(seed)), etc. 

That said, all we have to do is to provide a seed (i.e., the starting point, or, the initial element) and then a function  to be applied to the previous element to produce a new element.  

```
new long[]{ 0L, 1L } // as the 1st parameter
```
For the Fibonacci "kickstart" we need two elements: `0` and `1`. Then, the sum of both will provide the next element and so on. That said, this array will represent a pair of the first values of the Fibonacci sequence, as the first element of the stream.

```
p->new long[]{ p[1], p[0]+p[1] }) // as the 2nd parameter
```

So, this object `p` will create a new array containing two elements: 
* `p[1]`: which is the previous array in the position 1;
* `p[0] + p[1]`: which is the previous array in the position 0 plus its position 1;

```
.map(p -> p[0])
```

The thing is, we have a stream of pair elements going on until now, however, our main goal is to print elements of this sequence. To get the "current" element of this operation, by "mapping" the current pair of values of this stream to a single element, in this case, the array in position `0`.

```
.limit(10)
```

This is important, as said before, this will _Return an infinite sequential ordered Stream_ by default. So, in order not to have this running forever, with your PC burning out, we define a "limit" to this operation, by processing the first 10 elements only.

```
.map(p->p+" ")
```

This is silly, as we want to just print the sequence, it would be nice if we have a separator for each element, so here it is.

```
.forEach(System.out::print)
```

The `forEach` is a terminal operation as well, and what it'll do is to iterate over the resulting collection of the Stream. So, here we're just printing the current element by using the well-known `System.out.print`. 

If you're not familiar with expressions like this `System.out::print` yet, better check out about method reference, which is a special type of lambda expression, very useful to reduce boilerplate and improve readability. Next chapter suggested to write about is on Java functional programming.