如何在 Java 8 中创建漂亮的迭代

2022-01-24 00:00:00 iteration java-8 java

灵感来自 Adam Bien 的博客 我想替换一个常见的在 Java 7 中迭代成 Java 8 中更好的版本.旧代码如下所示:

Inspired by Adam Bien's weblog I wanted to replace a common iteration in Java 7 into a nicer one in Java 8. The older code looked like this:

void repeatUsingJava7(int times) {
    for (int i = 0; i < times; i++) {
        doStuff();
        doMoreStuff();
        doEvenMoreStuff();
    }
}

...这不太好.所以我用 Adam Bein 的例子把它替换成了这个:

...which is not too nice. So I replaced it using Adam Bein's example into this:

void repeatUsingJava8(int times) {
    IntStream.range(0, times).forEach(
        i -> {
            doStuff();
            doMoreStuff();
            doEvenMoreStuff();
        }
    );
}

...这是朝着正确方向迈出的一步,但并没有使代码更易于阅读,并且还引入了一个不需要的变量i,以及一对额外的大括号.所以现在我想知道是否有其他方法可以编写此代码,这将使其更好、更易于阅读,主要使用 Java 8.

...which is a step in the right direction, but does not make the code much simpler to read, and also introduces an unneeded variable i, as well as an extra pair of curly brackets. So now I'm wondering if there are other ways to write this code which will make it even nicer and easier to read, primarily using Java 8.

推荐答案

为了完整起见,这里有一个不需要计数器变量的解决方案:

Just for completeness, here is a solution which doesn’t need the counter variable:

void repeatUsingJava8(int times) {
    Collections.<Runnable>nCopies(times, ()->{
        doStuff();
        doMoreStuff();
        doEvenMoreStuff();
    }).forEach(Runnable::run);
}

如果只有一个方法被多次调用,它会变得更具可读性,因为在这种情况下它可以写成,例如

It would become more readable if there is only one method to be invoked multiple times as in that case it could be written as, e.g.

void repeatUsingJava8(int times) {
    Collections.<Runnable>nCopies(times, this::doStuff).forEach(Runnable::run);
}

如果必须是Streams,上面的代码等价于

If it has to be Streams, the code above is equivalent to

void repeatUsingJava8(int times) {
    Stream.<Runnable>generate(()->this::doStuff).limit(times).forEach(Runnable::run);
}

然而,这些替代方案并不比旧的 for 循环更好.如果您考虑 parallel 执行,这是 Stream 相对于普通 for 循环的真正优势,那么仍然存在基于众所周知的、已批准的替代方案API:

However, these alternatives are not really better than the good old for loop. If you consider parallel execution, which is a real advantage of Streams over ordinary for loops, there are still alternatives based on commonly known, approved APIs:

ExecutorService es=Executors.newCachedThreadPool();
es.invokeAll(Collections.nCopies(times, Executors.callable(()->{
    doStuff();
    doMoreStuff();
    doEvenMoreStuff();
})));

相关文章