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


Groups > comp.lang.java.programmer > #39014 > unrolled thread

Can I get the number where the stream stops

Started byCecil Westerhof <Cecil@decebal.nl>
First post2019-07-28 00:54 +0200
Last post2019-07-28 12:54 +0000
Articles 2 — 2 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  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

#39014 — Can I get the number where the stream stops

FromCecil Westerhof <Cecil@decebal.nl>
Date2019-07-28 00:54 +0200
SubjectCan I get the number where the stream stops
Message-ID<87y30jnl62.fsf@munus.decebal.nl>
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

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.

In this case I could use:
     Stream.
         iterate(new long[]{0, 1}, t -> t[1] > 0, t -> new long[]{t[1], t[0] + t[1]}).
         count()

And when n greater or equal generate an exception. But that works
because calculating the count is an inexpensive operation. How to
solve it when it is an expensive operation?
Or do I want to much? ;-)

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

[toc] | [next] | [standalone]


#39015

FromAndreas Leitgeb <avl@logic.at>
Date2019-07-28 12:54 +0000
Message-ID<slrnqjr6o9.36g.avl@logic.at>
In reply to#39014
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.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web