Reputation: 380
My question concerns the Java foreach loop, introduced in Java 5, and Iterable.forEach()
, introduced in Java 8.
Let's say that a program exists with a List of String values, and the function of that program is to iterate over each individual string and use it as a method parameter.
Such a program could look like this as of Java 5:
for (String s : stringList) {
doSomething(s);
}
However, with the introduction of Iterable.forEach()
in Java 8, such a program could look like this:
stringList.forEach(this::doSomething);
My question is, is there any reason to use Iterable.forEach()
instead of the foreach loop beyond the saving of a couple lines?
Upvotes: 1
Views: 584
Reputation: 33865
Here are 3 differences to consider between the two:
Lambdas can not capture non-final variables.
A forEach
does not allow for break
/continue
.
Checked exceptions must be caught within a passed lambda (since the type is 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
});
}
Upvotes: 5
Reputation: 4695
The fundamental benefit is that of internal iteration that you can utilize with forEach
should the library decide to do it. When using the enhanced for loop (for x : xs
), you insist on external iteration.
The idea is that you want some function to take every element of a list (or Iterable
) and do something with it. The non-functional (traditional in Java) is to iterate over the list in your code and do it. This is called external iteration. This forces sequential execution.
With Java 8, you could create and pass lambda expression. So, you pass the behavior or function that accepts the element. Thus, you relinquish the control over iteration and let the list implementation (library code, so to speak) take care of iteration, possibly parallelizing the efforts.
Upvotes: 3
Reputation: 1189
Providing a forEach
makes the action to be performed on the elements pluggable and very flexible. It can be an immediate lambda, a MethodHandle or even a MethodHanlde dynamically composed from a static portion of behavior and a runtime-defined part of it. Internally, the creation of an explicit Iterator
object may be avoided. Otherwise, you can, of course, simulate the same behavior by an external loop. This might not look so nice though.
Upvotes: 5
Reputation: 6363
In the new Java8 API you can do things like
stringList.stream ().filter(...).map(...).forEach(...)
Which can many times be cleaner and less error prone than just doing the same transformationsize and filtering inside a for each for loop.
Upvotes: 2