用Iterable.forEach替换foreach循环纯粹是化妆品吗?

时间:2016-06-25 14:23:11

标签: java foreach iterator java-8

我的问题涉及Java 5中引入的Java foreach循环和Java 8中引入的Iterable.forEach()

假设存在一个带有List of String值的程序,该程序的功能是迭代每个单独的字符串并将其用作方法参数。

这样的程序在Java 5中看起来像这样:

for (String s : stringList) {
    doSomething(s);
}

然而,随着Java 8中Iterable.forEach()的引入,这样的程序看起来像这样:

stringList.forEach(this::doSomething);

我的问题是,有没有理由使用Iterable.forEach()代替foreach循环而不是保存几行?

4 个答案:

答案 0 :(得分:5)

提供forEach可以对可插拔的元素执行操作,并且非常灵活。它可以是一个直接的lambda,一个MethodHandle,甚至是一个MethodHanlde,它是由行为的静态部分和运行时定义的部分动态组成的。在内部,可以避免创建显式Iterator对象。否则,您当然可以通过外部循环模拟相同的行为。这可能看起来不太好。

答案 1 :(得分:5)

以下是两者之间需要考虑的3个差异:

  • Lambdas无法捕获非最终变量。

  • forEach不允许break / continue

  • 必须在传递的lambda中捕获已检查的异常(因为类型为Consumer<...>)。

List<MyClass> list = ...;

MyClass mc = null;

for(MyClass e : list) {
    if(e.test("bla")) {
        mc = e;
        break;
    }
}               

list.forEach(e -> {
    if(e.test("bla")) {
        mc = e; // Does not compile
        break; // Also, does not compile
    }
});
void method() throws Exception {        
    ...
    for(MyClass e : list) {
        ...
        throw new Exception("Oops");
    }

    list.forEach(e -> {
        ...
        throw new Exception("Oops"); // Error: unhandled exception
    });
}

答案 2 :(得分:3)

基本的好处是内部迭代,如果库决定这样做,你可以使用forEach。使用增强型for循环(for x : xs)时,您坚持使用外部迭代

这个想法是你想要一些函数来获取列表的每个元素(或Iterable)并用它做一些事情。非功能性(Java中的传统)是迭代代码中的列表并执行它。这称为外部迭代。这迫使顺序执行。

使用Java 8,您可以创建并传递lambda表达式。因此,您传递接受该元素的行为或函数。因此,您放弃对迭代的控制,让列表实现(可以说是库代码)负责迭代,可能并行化工作。

答案 3 :(得分:2)

在新的Java8 API中,您可以执行

之类的操作
stringList.stream ().filter(...).map(...).forEach(...)

除了在每个for循环中进行相同的转换和过滤之外,它可以多次清洁且不易出错。