如何在以下示例中使用 lambda 表达式和流?

How to use lambda expressions and streams in the following example?

如何使用 lambda 表达式编写以下过程,以及如何使用流编写它?

Screen myScreen = new Screen();
Pattern myPattern = new Pattern("img.png");

Iterator<Match> it = myScreen.findAll(myPattern);
  while (it.hasNext())
    it.next().click();

您可以使用 Apache Commons Collections 实用程序来做到这一点。例如:

Iterator<Match> matches = s.findAll("someImage.png");
List<Match> list = IteratorUtils.toList(matches);
list.stream().forEach(Match::highlight);

如果你真的想为此使用带 lambda 的 Stream,你必须先将 Iterator 转换为 Stream,然后你可以使用这个 Stream 迭代你的对象并调用它们的 click 方法方法参考:

Iterator<Match> it = myScreen.findAll(myPattern);

// convert Iterator to Stream
Iterable<Match> iterable = () -> it;
Stream<Match> stream = StreamSupport.stream(iterable.spliterator(), false);

// invoke click on each object
stream.forEach(Match::click);

或者,如果您想使用显式 lambda 表达式:

stream.forEach(match -> match.click());

或者,在 Java 8 中,Iterator 接口有一个默认方法 forEachRemaining(Consumer)

那个可以解决你的问题,而不必求助于流。你可以简单地做:

Iterator<Match> it = myScreen.findAll(myPattern);
it.forEachRemaining(Match::click);

好吧,将会 一种像 for 循环或迭代器一样使用流进行迭代的方法 - 通过 Stream.iterate,但它会出现在 jdk-9。但它的使用并不那么简单——因为它的行为与 for 循环完全一样,因此并不完全符合您的预期。例如:

 Iterator<Integer> iter = List.of(1, 2, 3, 4).iterator();

 Stream<Integer> stream = Stream.iterate(iter.next(),
                   i -> iter.hasNext(), 
                   i -> iter.next()); 
     stream.forEach(System.out::println); // prints [1,2,3]

或者这样:

 Iterator<Integer> iter = List.of(1).iterator();

    Stream.iterate(iter.next(), i -> iter.hasNext(), i -> iter.next())
            .forEach(System.out::println); // prints nothing

对于您需要的情况,有 forEachRemaining,但没有 "magic",它在内部完全符合您的要求:

default void forEachRemaining(Consumer<? super E> action) {
    Objects.requireNonNull(action);
    while (hasNext())
        action.accept(next());
}