Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 generate stream of integer based on last value

I need to generate stream of integers that each value is based on the value before according to some math function.

For example - lets say I want to take last number and add 10: [1, 11, 21, 31, 41, ...]

of course the real function is much more complex.

I tried taking the fibonaci example but couldn't make it work:

Stream.iterate(new long[]{ 1, 1 }, p->new long[]{ p[1], p[0]+p[1] })
      .limit(92).forEach(p->System.out.println(p[0]));

I can only start at 1.

This is what I tried doing:

Stream.iterate(new long[]{ 1 }, p-> {p[0], p[0] + 10})
.limit(4).forEach(p->System.out.println(p[0]));
like image 355
Ido Barash Avatar asked Jun 26 '17 15:06

Ido Barash


People also ask

How we can create an infinite stream in Java 8?

We created an infinite stream using an iterate() method. Then we called a limit() transformation and a collect() terminal operation. Then in our resulting List, we will have first 10 elements of an infinite sequence due to a laziness of a Stream.

How do I get the last element of a stream?

The other way to get the last element of the stream is by skipping all the elements before it. This can be achieved using Skip function of Stream class. Keep in mind that in this case, we are consuming the Stream twice so there is some clear performance impact.


2 Answers

According to Stream#iterate method docs:

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.

The first element (position 0) in the Stream will be the provided seed. For n > 0, the element at position n, will be the result of applying the function f to the element at position n - 1.

So, for your example, it should work as follows:

Stream.iterate(1L, x -> x + 10L)
    .limit(4)
    .forEach(System.out::println); // 1 11 21 31

If your function is too complex, you can abstract it to a method:

private long complexFunction(long value) {
    return <very_complex_calculation with value>;
}

long N = 4L;

Stream.iterate(1L, this::complexFunction)
    .limit(N)
    .forEach(System.out::println);
like image 73
fps Avatar answered Dec 24 '22 08:12

fps


You can use an AtomicLong to keep another variable when iterating. For the Fibonacci sequence where you would keep the largest of the 2 numbers and in the AtomicLong and the iteration variable would be the smallest. E.g.

AtomicLong fibonacci = new AtomicLong(1);
Stream.iterate(1L, x -> fibonacci.getAndAdd(x))
    .limit(10)
    .forEach(i -> System.out.println(fibonacci.get()));
like image 42
Manos Nikolaidis Avatar answered Dec 24 '22 09:12

Manos Nikolaidis