java - 如何实现用于流式传输斐波那契数的 Spliterator?

标签 java concurrency parallel-processing java-8 spliterator

我正在玩 Java 8 Spliterator并创建了一个将斐波那契数字流式传输到给定的 n。所以对于斐波那契数列 0, 1, 1, 2, 3, 5, 8, ...

n    fib(n)
-----------
-1   0
1    0
2    1
3    1
4    2

以下是我的实现,它在用完堆栈内存之前打印一堆 1。你能帮我找到错误吗? (我认为它没有推进 currentIndex 但我不确定将其设置为什么值)。

编辑 1:如果您决定回答,请保持与问题的相关性。这个问题不是关于高效的斐波那契数生成;这是关于学习 split 器。

斐波那契拆分器:

@RequiredArgsConstructor
public class FibonacciSpliterator implements Spliterator<FibonacciPair> {
    private int currentIndex = 3;
    private FibonacciPair pair = new FibonacciPair(0, 1);

    private final int n;

    @Override
    public boolean tryAdvance(Consumer<? super FibonacciPair> action) {
//        System.out.println("tryAdvance called.");
//        System.out.printf("tryAdvance: currentIndex = %d, n = %d, pair = %s.\n", currentIndex, n, pair);

        action.accept(pair);

        return n - currentIndex >= 2;
    }

    @Override
    public Spliterator<FibonacciPair> trySplit() {
//        System.out.println("trySplit called.");

        FibonacciSpliterator fibonacciSpliterator = null;

        if (n - currentIndex >= 2) {
//            System.out.printf("trySplit Begin: currentIndex = %d, n = %d, pair = %s.\n", currentIndex, n, pair);

            fibonacciSpliterator = new FibonacciSpliterator(n);

            long currentFib = pair.getMinusTwo() + pair.getMinusOne();
            long nextFib = pair.getMinusOne() + currentFib;

            fibonacciSpliterator.pair = new FibonacciPair(currentFib, nextFib);
            fibonacciSpliterator.currentIndex = currentIndex + 3;

//            System.out.printf("trySplit End: currentIndex = %d, n = %d, pair = %s.\n", currentIndex, n, pair);
        }

        return fibonacciSpliterator;
    }

    @Override
    public long estimateSize() {
        return n - currentIndex;
    }

    @Override
    public int characteristics() {
        return ORDERED | IMMUTABLE | NONNULL;
    }
}

斐波那契对:

@RequiredArgsConstructor
@Value
public class FibonacciPair {
    private final long minusOne;
    private final long minusTwo;

    @Override
    public String toString() {
        return String.format("%d %d ", minusOne, minusTwo);
    }
}

用法:

Spliterator<FibonacciPair> spliterator = new FibonacciSpliterator(5);

StreamSupport.stream(spliterator, true)
    .forEachOrdered(System.out::print);

最佳答案

除了您的代码不完整之外,您的 tryAdvance 方法中至少有两个错误是可识别的。首先,你实际上并没有取得任何进步。您没有修改拆分器的任何状态。其次,您无条件地调用操作的 accept 方法,这与您返回的是条件值而不是 true 的事实不符。

tryAdvance 的目的是:

  • 顾名思义,尝试前进,即计算下一个值
  • 如果有下一个值,调用 action.accept 并返回 true
  • 否则只返回false

进一步注意,您的trySplit() 看起来不太有说服力,我什至不知道从哪里开始。你最好继承 AbstractSpliterator 而不是实现自定义 trySplit()。无论如何,您的操作不会从并行执行中受益。使用该源构建的流只有在将其与安静且昂贵的按元素操作链接在一起时才能从并行执行中获得优势。

关于java - 如何实现用于流式传输斐波那契数的 Spliterator?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34787295/

相关文章:

multithreading - 如何才能充分利用 .NET 4.0 中新增强的并行功能?

java - 如何在java中捕获此异常并记录它

java - 如何迭代 JFXTreeTableView 中的行?

java - 标签的文本在 Java 中没有改变

java - future 超时是否会终止线程执行

c++ - Eigen 中的多线程(未使用 OpenMP)

java - Hibernate 的外键问题(Bug?)

java - STS 项目出现错误,无法读取或不是有效的 ZIP 文件

java - Android 中的并发文件访问

parallel-processing - OpenMP 在线程中调用子程序