Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #39014 > unrolled thread
| Started by | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| First post | 2019-07-28 00:54 +0200 |
| Last post | 2019-07-28 12:54 +0000 |
| Articles | 2 — 2 participants |
Back to article view | Back to comp.lang.java.programmer
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
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2019-07-28 00:54 +0200 |
| Subject | Can 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]
| From | Andreas Leitgeb <avl@logic.at> |
|---|---|
| Date | 2019-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