Java 8 打破 forEach 的替代行动

5 java functional-programming java-8

我确实有以下课程:

public class CloseableRepeater<R extends Closeable> {

    /**
     * Repeats the supplier until the stop condition becomes <code>true</code>.
     *
     * @param supplier The supplier to be repeated.
     * @param until  The stop condition.
     * @param times  The maximum repeat times.
     * @return The result.
     */
    public Optional<R> repeat(Supplier<R> supplier, Predicate<R> until, int times) {
        R r = null;
        for (int i = 0; i < times; i++) {
            r = supplier.get();
            if (until.test(r)) {
                break;
            } else {
                try {
                    r.close();
                } catch (IOException e) {
                    // Ignore
                }
            }
        }
        return Optional.of(r);
    }

}
Run Code Online (Sandbox Code Playgroud)

基本上,它重复一个动作,直到满足条件并关闭不满足它的项目。


我的问题

是否有可能repeat使用函数式编程重写该方法?


我知道代码已经足够好了,但是这个问题的目标是提高我的函数式编程技能并找到它的局限性

我得到的最接近的是:

public Optional<R> repeat(Supplier<R> supplier, Predicate<R> until, int times) {
    return IntStream.range(0, times).mapToObj(i -> supplier.get()).filter(until).findFirst();
}
Run Code Online (Sandbox Code Playgroud)

但该close部分丢失了。

小智 3

根据@VinceEmigh的评论,我想我已经找到了解决方案:

   public Optional<R> functionalRepeat(Supplier<R> supplier, Predicate<R> until, int times) {
        return Stream.generate(supplier).limit(times).filter(until.or(t -> {
            try {
                t.close();
            } catch (IOException e) {
                // Ignore
            }
            return false;
        })).findFirst();
    }
Run Code Online (Sandbox Code Playgroud)

这个想法是close通过将until谓词与另一个执行结束的谓词链接起来来调用 while 过滤,利用它是涉及短路逻辑 OR 的事实。

当且仅当谓词为真时,过滤条件为真until,因此它们在逻辑上是等价的。

更新

实际上,上面的代码并不等同于原始代码,因为它在不匹配时生成一个空可选,而原始代码生成一个包含最后一个不匹配元素的可选。

  • 当您拥有元素“ABCDEF”并且谓词接受“C”和“D”时,“findFirst()”保证返回“C”,但您的代码假定这意味着它永远无法处理“D”。这是无法保证的,实际上,您的谓词可能必须在并行流中处理“D”。当*遇到顺序*中较早的位置还有已接受的“C”时,流将正确删除“D”,但此时您尚未关闭“D”。 (3认同)