scott parent
scott parent

Reputation: 77

Transforming a while loop to a stream in Java 8

As an exercise I'm converting some old code to functional streams. I don't know much about streams. It seems like it should be simple to convert this code, but I haven't had much luck. The method starts at a given integer, passes it to isPrime, which returns true if it's prime. and then hands off the new(next) prime number to be printed. If isPrime is false i is incremented and we check the next integer.

private static int nextPrime(final int number) {
    int i = number + 1;

    while (!isPrime(i)) {
        i++;
    }

    return i;
}

Upvotes: 6

Views: 11587

Answers (2)

Lucas Cimon
Lucas Cimon

Reputation: 2043

Based on this answer, for an object like an Enumeration<T> for example, where you can only call .hasMoreElements() & .nextElement(), you can use this kind of code :

public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) {
    return StreamSupport.stream(
        new Spliterators.AbstractSpliterator<T>(Long.MAX_VALUE, Spliterator.ORDERED) {
            public boolean tryAdvance(Consumer<? super T> action) {
                if(e.hasMoreElements()) {
                    action.accept(e.nextElement());
                    return true;
                }
                return false;
            }
            public void forEachRemaining(Consumer<? super T> action) {
                while(e.hasMoreElements()) action.accept(e.nextElement());
            }
    }, false);
}

Upvotes: -1

Jacob G.
Jacob G.

Reputation: 29680

I see no reason to use a Stream for this other than to take advantage of parallelism (if the primes happen to be very far apart, but this won't be true within int bounds, so there's essentially no benefit).

You can iterate over an IntStream of ascending integers (starting from number + 1) and filter only the prime numbers. When one is inevitably found, you can return the first.

private static int nextPrime(final int number) {
    return IntStream.iterate(number + 1, i -> i + 1)
                    .filter(Test::isPrime)
                    .findFirst()
                    .getAsInt();
}

Note: The class that I used to test this is called Test, as seen by the method reference. You should change that to your class name.

Upvotes: 7

Related Questions