如何在Java8中创建好的迭代

如何在Java8中创建好的迭代,java,java-8,iteration,Java,Java 8,Iteration,受此启发,我想将Java7中常见的迭代替换为Java8中更好的迭代。较旧的代码如下所示: void repeatUsingJava7(int times) { for (int i = 0; i < times; i++) { doStuff(); doMoreStuff(); doEvenMoreStuff(); } } void repeat(int count, Runnable... actions) { I

受此启发,我想将Java7中常见的迭代替换为Java8中更好的迭代。较旧的代码如下所示:

void repeatUsingJava7(int times) {
    for (int i = 0; i < times; i++) {
        doStuff();
        doMoreStuff();
        doEvenMoreStuff();
    }
}
void repeat(int count, Runnable... actions) {
    IntStream.range(0, count).forEach(i -> Arrays.asList(actions).forEach(Runnable::run));
}

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

在这种情况下,使用流没有任何优势。流对于处理包含多个相同类型元素的集合、数组和其他数据结构非常有用


在这里,您不需要处理任何数据,只需多次重复相同的操作。没有理由为此更换旧的for循环。

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

void repeatUsingJava8(int times) {
    Collections.<Runnable>nCopies(times, ()->{
        doStuff();
        doMoreStuff();
        doEvenMoreStuff();
    }).forEach(Runnable::run);
}
如果必须是
Stream
s,则上述代码相当于

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

正如其他人指出的,对于这个特定的示例,用流替换简单的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 repeatUsingJava7(int times) {
    for (int i = 0; i < times; i++) {
        doStuff();
        doMoreStuff();
        doEvenMoreStuff();
    }
}
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();
        }
    }
}
void repeatOldWay(整数计数、可运行…操作){
for(int i=0;i

真正的优势在于调用站点,您只需传入计数和一个或多个lambda表达式或方法引用,而无需复制嵌套for循环逻辑。

您还可以使用from谓词:

IntStream.range(0, 10).sorted().filter(i -> i > 5).forEach(System.out::println);

排序和文件管理器是附加的。

可能的重复我看不出它们有什么相似之处:我的问题是关于多次重复操作,而您提到的是关于在列表上迭代。第二种表达代码的方法不是引入“一个不需要的变量I以及一对额外的花括号”. 两个代码片段都有一个变量
i
,并且都有相同数量的花括号。嗯,它们是等价的……我认为这使代码更具表现力,我相信这就是Java8中streams和lambdas的全部内容。但是我同意,我写第二个例子的方式并没有使代码变得更简单,这就是为什么我要问是否有其他的方法来写它的原因!一个常见的危险是,每个人都想在任何事情上使用新的闪亮工具,即使旧的生锈工具很好。当我看到IDE建议将集合上的普通for循环转换为forEach时,大多数情况下,这样做是错误的。使用新的闪亮工具,让你发挥杠杆作用。但是for循环没有什么问题。
IntStream.range(0, 10).sorted().filter(i -> i > 5).forEach(System.out::println);