将Java 8中的while循环转换为流

6

作为一个练习,我正在将一些旧代码转换为函数式流。我并不了解流的很多东西。似乎将这段代码转换为流应该很简单,但我没有太多成功的经验。这个方法从给定的整数开始,将其传递给isPrime函数,如果它是素数则返回true,然后将新的(下一个)素数交给打印程序打印。如果isPrime是false,那么增加i并检查下一个整数。

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

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

    return i;
}

6
为什么你认为需要转换这样一个简单的循环?当你“没有太大运气”时,遇到了什么问题?当int值范围内没有下一个质数时,你的方法应该做什么?当前的溢出行为并不令人信服。 - Holger
4
作为一项练习,我前几天尝试了使用新的编程语言来开发一个简单的网页应用程序。 - dieter
2个回答

7

我认为除了利用并行处理(如果质数之间的距离很远,但在int类型范围内这种情况几乎不会发生,所以这种方法基本上没有任何好处),没有理由使用Stream

您可以迭代升序整数的IntStream(从number + 1开始),并仅过滤出质数。当必然找到一个质数时,您可以返回第一个质数。

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

注意: 我用来测试的类名叫做Test,可以从方法引用中看到。你应该将其改为你自己的类名。


无限流永远不会返回一个空的可选项。 - shmosel
没错,我会更好地传达。 - Jacob G.
1
@Aominè 很好的发现,我忘记了 OptionalInt 不是 get ;) - Jacob G.
4
我明白这不需要一个流。我只是尝试通过转换已经运行的代码来学习函数式编程。你给的代码帮了我很大的忙。我正在慢慢理解它。 - scott parent
4
我更倾向于使用IntStream.rangeClosed(number + 1,Integer.MAX_VALUE); 这样更高效,并且在没有更大的质数时抛出NoSuchElementException的行为比溢出更合理... - Holger

-1

根据这个答案,例如对于像Enumeration<T>这样的对象,你只能调用.hasMoreElements().nextElement(),你可以使用以下代码:

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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接