Hi Tagir, this looks good. I wonder, however, if the signature should accept a wider range of types, i.e., something like
static <T, S extends T> Stream<T> iterate(S seed, Predicate<S> predicate, UnaryOperator<S> f) I know that the corresponding static <T> Stream<T> iterate(T seed, UnaryOperator<T> f) is less general than that, but I don't know whether this is the outcome of a thoughtful decision or just an oversight. What do you think? Regards, Stefan 2016-02-14 15:53 GMT+01:00 Tagir F. Valeev <amae...@gmail.com>: > Hello! > > I wanted to work on foldLeft, but Brian asked me to take this issue > instead. So here's webrev: > http://cr.openjdk.java.net/~tvaleev/webrev/8072727/r1/ > > I don't like iterator-based Stream source implementations, so I made > them AbstractSpliterator-based. I also implemented manually > forEachRemaining as, I believe, this improves the performance in > non-short-circuiting cases. > > I also decided to keep two flags (started and finished) to track the > state. Currently existing implementation of infinite iterate() does > not use started flag, but instead reads one element ahead for > primitive streams. This seems wrong to me and may even lead to > unexpected exceptions (*). I could get rid of "started" flag for > Stream.iterate() using Streams.NONE, but this would make object > implementation different from primitive implementations. It would also > be possible to keep single three-state variable (byte or int, > NOT_STARTED, STARTED, FINISHED), but I doubt that this would improve > the performance or footprint. Having two flags looks more readable to > me. > > Currently existing two-arg iterate methods can now be expressed as a > partial case of the new method: > > public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) { > return iterate(seed, x -> true, f); > } > (same for primitive streams). I may do this if you think it's > reasonable. > > I created new test class and added new iterate sources to existing > data providers. > > Please review and sponsor! > > With best regards, > Tagir Valeev. > > (*) Consider the following code: > > int[] data = {1,2,3,4,-1}; > IntStream.iterate(0, x -> data[x]) > .takeWhile(x -> x >= 0) > .forEach(System.out::println); > > Currently this unexpectedly throws an AIOOBE, because > IntStream.iterate unnecessarily tries to read one element ahead. >