Java 8流手动短路

Java 8 stream short circuit manually

有什么方法可以手动使流短路(如在 findFirst 中)?

示例:

想象一本按单词大小和字母排序的巨大字典:

cat
... (many more)
lamp
mountain
... (many more)

仅准备好并从头开始计算文件,return当行大小超过 4 时立即:

read cat, compute cat
...
read tree, compute lamp
read mountain, return

下面的代码很简洁,但是没有利用流的顺序,每一行都要准备好:

try (Stream<String> lines = Files.lines(Paths.get(DICTIONARY_PATH))) {
        return lines
                // filter for words with the correct size
                .filter(line -> line.length() == 4)
                // do stuff...
                .collect(Collectors.toList());
}

答案基于Limit a stream by a predicate, processing correctly stops when predicate returns false. Hopefully this method comes available in Java 9

private static List<String> getPossibleAnswers(int numberOfChars, char[][] possibleChars) throws IOException {
    try (Stream<String> lines = Files.lines(Paths.get(DICTIONARY_PATH)) {
        return takeWhile(lines, line -> line.length() <= numberOfChars)
                // filter length
                .filter(line -> line.length() == numberOfChars)
                // do stuff
                .collect(Collectors.toList());
    }
}

static <T> Spliterator<T> takeWhile(Spliterator<T> splitr, Predicate<? super T> predicate) {
    return new Spliterators.AbstractSpliterator<T>(splitr.estimateSize(), 0) {              boolean stillGoing = true;

        @Override
        public boolean tryAdvance(Consumer<? super T> consumer) {
            if (stillGoing) {
                boolean hadNext = splitr.tryAdvance(elem -> {
                    if (predicate.test(elem)) {
                        consumer.accept(elem);
                    } else {
                        stillGoing = false;
                    }
                });
                return hadNext && stillGoing;
            }
            return false;
        }
    };
}

static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
    return StreamSupport.stream(takeWhile(stream.spliterator(), predicate), false);
}