首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 9 Stream.iterate​(T种子,Predicate<?超级T> hasNext,UnaryOperator<T> next)调用next之后的hasNext

Java 9 Stream.iterate​(T种子,Predicate<?超级T> hasNext,UnaryOperator<T> next)调用next之后的hasNext
EN

Stack Overflow用户
提问于 2022-06-02 18:15:59
回答 1查看 152关注 0票数 1

我的理解是,它需要检查hasNext,然后如果它是true,则调用下一个方法来获取迭代器中的元素。

问题:

它在检索元素后调用hasNext,在我的示例中,使用next检索最后一个元素并检查hasNext,然后返回false并结束循环。因此,我处理N-1元素而不是N元素。

或者,我使用了下面的代码。

代码语言:javascript
复制
Stream.generate(() -> j)
    .takeWhile(SlidingWindow::hasNextTimePeriod)
    .map(slider -> slider.next())

复制代码:

代码语言:javascript
复制
@Slf4j
class Java9StreamTest {

    @Test
    void testStream() {

        final SlidingWindows slidingWindows = new SlidingWindows();

        Stream.iterate(slidingWindows.next(), j -> slidingWindows.hasNext(), j -> slidingWindows.next())
                .forEach(value -> log.info("{}", value));
    }
}

class SlidingWindows {
    private final List<String> list = List.of("A", "B", "C");
    private int count = 0;

    public boolean hasNext() {
        return count < list.size();
    }

    public String next() {
        final String result = list.get(count);
        count = count + 1;
        return result;
    }    
}

产出:

代码语言:javascript
复制
20:20:03.485 [main] INFO mohan.stream.Java9StreamTest - A
20:20:03.489 [main] INFO mohan.stream.Java9StreamTest - B

缺少最后一个元素C

它的工作方式类似于for循环,在Java中使用hasNextnext是有误导性的。

在流中,什么等同于下面的代码?

代码语言:javascript
复制
 while(slidingWindows.hasNext()) { 
    final String next = slidingWindows.next(); 
    log.info("{}", next); 
 }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-02 19:32:13

根据文档,Stream.iterate()利用引擎盖下的for循环:

Stream.iterate应该生成与对应的for-循环相同的元素序列:

对于(T index=seed;hasNext.test(索引);index =next.apply(索引)){.},如果hasNext谓词不保留种子值,则结果序列可能为空。否则,第一个元素将是提供的种子值,下一个元素(如果存在)将是将next函数应用于种子值的结果,等等,直到hasNext谓词指示流应该终止

因此,基本上,iterate()种子的第一个参数对应于for循环的初始化表达式,第二个参数(谓词)充当终止表达式,第三个参数(一元操作符)扮演增量表达式()的角色。

示例

让我们来看看下面的几个例子:

代码语言:javascript
复制
Iterator<String> iter = List.of("A", "B", "C").iterator();

Stream.iterate(iter.next(), str -> iter.hasNext(), str -> iter.next())
    .forEach(System.out::println);

这与以下几点相同:

代码语言:javascript
复制
Stream.generate(() -> "dummy")
    .map(str -> iter.next()) // requesting the element
    .peek(str -> System.out.println(str + " <- invoking next()"))
    .takeWhile(str -> {
        boolean result = iter.hasNext(); // checking whether the next element exists
        System.out.println(result + " <- invoking hasNext()");
        return result;
    })
    .forEach(str -> System.out.println(str + " <- has reached the terminal operation\n"));

第二个流的输出:

代码语言:javascript
复制
A <- invoking next()
true <- invoking hasNext()
A <- has reached the terminal operation

B <- invoking next()
true <- invoking hasNext()
B <- has reached the terminal operation

C <- invoking next()
false <- invoking hasNext()

让我们探讨所有的行动:

  • 种子iter.next()将检索第一个元素A (在第二个流中,它将由map操作完成)。然后将触发谓词iter.next()

然后,

  • 将检索第二个元素B,谓词将起作用。

然后,

  • 将跟随第三个元素C,谓词iter.next()将返回false,因为源已经耗尽。

结论:在这两种情况下,在执行谓词之前从源抓取最后一个元素C,并且由于源已经为空,谓词将被求值为false,该元素将被抛出。

怎么修呢?

要使它成功地从源检索所有元素,您需要交换maptakeWhile,即首先检查是否有下一个元素,然后才请求下一个元素

代码语言:javascript
复制
Iterator<String> iter = List.of("A", "B", "C").iterator();

Stream.generate(() -> "dummy")
    .takeWhile(str -> iter.hasNext())
    .map(str -> iter.next())
    .forEach(System.out::println);

输出:

代码语言:javascript
复制
A
B
C

此修复只适用于组合takeWhile + map,但不能更改iterate()的行为。

正如@Slow在注释中提到的那样,如果您使SlidingWindows类实现了Iterator接口,那么您可以使用StreamSupport实用程序类,它将负责将所有元素转换成流,如这里所述:Why does Iterable not provide stream() and parallelStream() methods?

注意,它还需要将迭代器转换为Spliterator的实例,这可以通过使用Spliterators实用程序类的静态方法spliteratorUnknownSize()来完成。

代码语言:javascript
复制
StreamSupport.stream(
        Spliterators.spliteratorUnknownSize(iter, Spliterator.ORDERED), 
        false) // a flag that denotes whether the stream should be parallel
    .forEach(System.out::println);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72480687

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档