Java 8流手动短路[重复]

Posted

技术标签:

【中文标题】Java 8流手动短路[重复]【英文标题】:Java 8 stream short circuit manually [duplicate] 【发布时间】:2017-01-20 04:53:54 【问题描述】:

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

示例:

想象一个按字长和字母排序的巨大字典:

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

仅从头开始准备和计算文件,当行大小超过 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());

【问题讨论】:

相关:***.com/questions/20746429/… 你要的一般叫takewhile。根据this question,似乎没有内置的方法可以做到这一点,但你可以自己写一个。 【参考方案1】:

根据Limit a stream by a predicate 回答,当谓词返回false 时正确停止处理。希望这种方法在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);

【讨论】:

与经典循环相比,这非常低效。 @aventurin 使用 java9 可能会有更快的实现。至少代码简洁,不需要临时变量。 流 API 可能会向程序员隐藏它背后的膨胀,但没有什么魔法可以减少 CPU 周期数、内存重新分配(ArrayList-collector)或额外的对象和类创建。除此之外,使用循环的等效代码更容易理解,只需要三行代码加上两个变量定义。 @aventurin 这不是问题的重点。但是,我的示例的问题陈述更大。我首先使用 while 循环对其进行编码,然后切换到流,因为我想增加对它们的了解。隐式版本:github.com/Journeycorner/tom-turbo-solver/commit/… 与功能版本:github.com/Journeycorner/tom-turbo-solver/blob/master/src/at/…。如果您可以用更少的代码行编写代码,而无需省略括号,请给我写一个拉取请求;)。

以上是关于Java 8流手动短路[重复]的主要内容,如果未能解决你的问题,请参考以下文章

我需要手动取消订阅吗? - Angular 8 [重复]

是否需要手动销毁和关闭 java.lang.Process 的打开流?

Java中,static代码块创建的IO流需要手动关闭吗?

下载网页TS流视频无需手动合并

java 啥资源需要手动释放

如果流没有手动关闭,它啥时候关闭?