受Adam Bien's weblog的启发我希望将Java 7中的常见迭代替换为Java 8中更好的迭代。旧代码看起来像这样:
void repeatUsingJava7(int times) {
for (int i = 0; i < times; i++) {
doStuff();
doMoreStuff();
doEvenMoreStuff();
}
}
......这不太好。所以我用Adam Bein的例子替换了它:
void repeatUsingJava8(int times) {
IntStream.range(0, times).forEach(
i -> {
doStuff();
doMoreStuff();
doEvenMoreStuff();
}
);
}
...这是向正确方向迈出的一步,但不会使代码更易于阅读,还会引入一个不需要的变量i
,以及一对额外的花括号。所以现在我想知道是否有其他方法来编写这个代码,这将使它更好,更容易阅读,主要是使用Java 8.
答案 0 :(得分:5)
为了完整起见,这是一个不需要计数器变量的解决方案:
void repeatUsingJava8(int times) {
Collections.<Runnable>nCopies(times, ()->{
doStuff();
doMoreStuff();
doEvenMoreStuff();
}).forEach(Runnable::run);
}
如果只有一个方法可以被多个times
调用,那么它将变得更具可读性,因为在这种情况下它可以写成,例如。
void repeatUsingJava8(int times) {
Collections.<Runnable>nCopies(times, this::doStuff).forEach(Runnable::run);
}
如果必须是Stream
s,则上述代码等同于
void repeatUsingJava8(int times) {
Stream.<Runnable>generate(()->this::doStuff).limit(times).forEach(Runnable::run);
}
然而,这些替代方案并不比旧的for
循环好。如果您考虑parallel
执行,Stream
比普通for
循环更有优势,那么仍然有基于众所周知的已批准API的替代方案:
ExecutorService es=Executors.newCachedThreadPool();
es.invokeAll(Collections.nCopies(times, Executors.callable(()->{
doStuff();
doMoreStuff();
doEvenMoreStuff();
})));
答案 1 :(得分:4)
在这种情况下,我认为使用Streams没有任何优势。流对于处理包含多个相同类型元素的集合,数组和其他数据结构非常有用。
在这里,您不处理任何数据,只需多次重复相同的操作即可。没有理由为此目的替换旧的for循环。
答案 2 :(得分:1)
正如其他人所指出的那样,对于这个具体的例子,用流替换简单的for循环不一定更好。但是,如果您尝试解决的问题更为普遍,则会出现优势。例如,假设您需要重复一些作为参数传递的代码,而不是重复某些特定代码 n 次。考虑:
void repeat(int count, Runnable action) {
IntStream.range(0, count).forEach(i -> action.run());
}
现在你可以写了,
repeat(3, () -> System.out.println("Hello!"));
或者
repeat(4, this::doStuff);
或许执行单个操作 n 次,您希望执行多个操作 n 次。你可以这样做:
void repeat(int count, Runnable... actions) {
IntStream.range(0, count).forEach(i -> Arrays.asList(actions).forEach(Runnable::run));
}
然后你就可以写:
repeat(5, this::doStuff, this::doMoreStuff, this::doEvenMoreStuff);
repeat
实现比传统的Java 7方式更简洁(可能更简洁):
void repeatOldWay(int count, Runnable...actions) {
for (int i = 0; i < count; i++) {
for (Runnable r : actions) {
r.run();
}
}
}
真正的优势在于调用站点,您可以在其中简单地传入一个count和一个或多个lambda表达式或方法引用,而不是复制嵌套的for循环逻辑。
答案 3 :(得分:0)
您也可以使用谓词:
IntStream.range(0, 10).sorted().filter(i -> i > 5).forEach(System.out::println);
已排序且文件管理器是附加的。