Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #39015

Re: Can I get the number where the stream stops

From Andreas Leitgeb <avl@logic.at>
Newsgroups comp.lang.java.programmer
Subject Re: Can I get the number where the stream stops
Date 2019-07-28 12:54 +0000
Organization A noiseless patient Spider
Message-ID <slrnqjr6o9.36g.avl@logic.at> (permalink)
References <87y30jnl62.fsf@munus.decebal.nl>

Show all headers | View raw


Cecil Westerhof <Cecil@decebal.nl> wrote:
> To play with streams I wrote the following stream to get a Fibonacci
> Number:
>     long fibonacciStream(int n) {
>         return Stream.
>             iterate(new long[]{0, 1}, t -> t[1] > 0, t -> new long[]{t[1], t[0] + t[1]}).
>             skip(n).
>             map(t -> t[0]).
>             findFirst().
>             get();
>     }
> This works like a charm as long as 0 <= n < 92. When it is called with
> 92 I get:
>     java.util.NoSuchElementException thrown: No value present

For me, running it gave a few more levels of trace, namely:
        at java.base/java.util.Optional.get(Optional.java:148)
        at FibTest.fibonacciStream(FibTest.java:10)

So, apparently, it is the .get() method that fails.

As it seems, the route to failure goes roughly like that:
   - somewhere near the 93rd element, the Predicate "t[1] > 0" goes to false,
        because the obtained fibonacci number doesn't fit into 63 bits and
        causes a wrap around to a negative value. Thus the stream only
        has 93 elements.
   - after skipping 93 elements, the resulting stream is empty.
   - the map on an empty stream is once again an empty stream.
   - findFirst() on an empty stream yields an empty Optional.
   - calling .get on an empty Optional yields the error you saw.

> Is there a way to get the value for which the stream does not work
> anymore? For example if called with:
>     fibonacciStream(121);
> I would like an exception that says that it cannot be called with
> values above 91.

Once you've skipped all elements, all relevant information is lost & gone forever.

You could change the payload of the stream to a triple, holding the
current count at index 2: 
  iterate( new long[]{0, 1, 1},
           t -> t[1] > 0,
           t -> new long[]{t[1], t[0] + t[1], t[2]+1 } ).

(I don't assume that Fibonacci sequence is your real task, but maybe
you can still insert an element counter into your real payload.)

And then, rather than calling skip(n), you rather "reduce" the stream
such that when end of stream is found before t[2] reaches n, then you
know the last value of t[2] and can throw an appropriate exception.

Back to comp.lang.java.programmer | Previous | Next — Previous in thread | Find similar | Unroll thread


Thread

Can I get the number where the stream stops Cecil Westerhof <Cecil@decebal.nl> - 2019-07-28 00:54 +0200
  Re: Can I get the number where the stream stops Andreas Leitgeb <avl@logic.at> - 2019-07-28 12:54 +0000

csiph-web