HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaModerate

Streaming int support

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
intstreamingsupport

Problem

This recent question Print Consecutive numbers by comparing two parameters frustrated me because I could not find a convenient way in Java 8 to support the conditions that are required. I answered it in a somewhat cumbersome way for Java 8... (the non-stream part of my answer is "OK" in terms of usability).

To reiterate the problem (as I interpreted it):


print the values in the range from a to b, where b may be less than a. e.g. from 1 to 3 will print 1, 2, 3 and from 3 to 1 will print 3, 2, 1.

What I really wanted was something like this:

IntSteam.loop(a, b, a < b ? ++ : --).foreach(System.out::println);


(yes, the above code makes no sense, treat it as pseudocode...).

Basically, stream from a value to another value, either incrementing, or decrementing the loop variable.

To make a real implementation of that, I figured the stream needs a seed, a terminal condition, and a stepping function. I implemented it like:

int a = 10;
    int b = 5;
    IntUnaryOperator op = a  i + 1
            : i -> i - 1;
    ForIntStream.until(a, v -> v == b, op).forEach(System.out::println);


The semantics there are: start from a, go until a == b, and use the operator to change the value.

While I was doing that, I also implemented a similar loop, that, instead of running until a condition, runs while a condition is true:

int a = 10;
    int b = 5;
    IntUnaryOperator op = a  i + 1
            : i -> i - 1;
    ForIntStream.of(a, v -> v != b, op).forEach(System.out::println);


Note that the difference there is that the 'of' stream terminates and does not include the terminating.

Here is the code that implements the above features. Any suggestions, or alternatives are welcome

```
import java.util.NoSuchElementException;
import java.util.PrimitiveIterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.IntConsumer;
import java.util.function.IntPredicate;
import java.util.function.IntUnaryOpe

Solution

After reading the problem description and before reading your code, I implemented something that was very similar to what you already have, which means that your approach to the problem is perfectly fine.

Spliterator - of unknown size

Instead of using

Spliterators.spliterator(it, Long.MAX_VALUE, Spliterator.ORDERED)


You should use

Spliterators.spliteratorUnknownSize(it, Spliterator.ORDERED)


Unnecessary method

The default implementation in the super interface for next() is:

@Override
default Integer next() {
    if (Tripwire.ENABLED)
        Tripwire.trip(getClass(), "{0} calling PrimitiveIterator.OfInt.nextInt()");
    return nextInt();
}


I really don't think you gain anything by making your own implementation of this method.

Additionally, your WhileIterator's forEachRemaining method can be removed and the default implementation used instead without any change in behavior.

Naming

I find the method ForIntStream.of to be hard to understand by looking at the name alone. Of what? Of a seed, a predicate and a unary operator? How about something like whilePredicate ?

Perfect for tests

Although using System.out.println to read the result and manually check it works perfectly fine in this case, real tests wouldn't hurt. ``

Code Snippets

Spliterators.spliterator(it, Long.MAX_VALUE, Spliterator.ORDERED)
Spliterators.spliteratorUnknownSize(it, Spliterator.ORDERED)
@Override
default Integer next() {
    if (Tripwire.ENABLED)
        Tripwire.trip(getClass(), "{0} calling PrimitiveIterator.OfInt.nextInt()");
    return nextInt();
}

Context

StackExchange Code Review Q#90548, answer score: 12

Revisions (0)

No revisions yet.