Java Stream API 具有从 Java 9 开始的方法 Stream::iterate,因此表示迭代步骤/状态的类可以实现如下:
class CubeSolver {
static final double EPS = 1E-06;
private double start, end, n, mid;
public CubeSolver(double s, double e, double n) {
this.start = s;
this.end = e;
this.n = n;
this.mid = (start + end) / 2;
}
// UnaryOperator<CubeSolver> for iteration
public CubeSolver next() {
if (done()) {
return this;
}
if (Math.pow(mid, 3) < n) {
start = mid;
} else if (Math.abs(n - Math.pow(mid, 3)) > EPS) {
end = mid;
}
return new CubeSolver(start, end, n);
}
// define end of calculation
public boolean done() {
return mid == 0 || Math.abs(n - Math.pow(mid, 3)) < EPS;
}
@Override
public String toString() {
return "root = " + mid;
}
}
那么基于流的解决方案是这样的:
- 使用
start、end、n 定义初始种子
- 使用
Stream::iterate 和hasNext 谓词来创建一个有限 流
2a) 或使用较旧的 Stream::iterate 而不使用 hasNext 但使用 Stream::takeWhile 操作来有条件地限制流 - 自 Java 9 起也可用
- 使用
Stream::reduceto get the last element of the stream
CubeSolver seed = new CubeSolver(1.8, 2.8, 8);
CubeSolver solution = Stream
.iterate(seed, cs -> !cs.done(), CubeSolver::next)
.reduce((first, last) -> last) // Optional<CubeSolver>
.orElse(null);
System.out.println(solution);
输出:
root = 2.0000002861022947
在 Java 11 中添加了静态 Predicate::not,因此使用 takeWhile 的 2a 解决方案可能如下所示:
CubeSolver seed = new CubeSolver(0, 7, 125);
CubeSolver solution = Stream
.iterate(seed, CubeSolver::next)
.takeWhile(Predicate.not(CubeSolver::done))
.reduce((first, last) -> last) // Optional<CubeSolver>
.orElse(null);
System.out.println(solution);
输出(对于 EPS = 1E-12):
root = 4.999999999999957