Which of the following is better practice in Java 8?
Java 8:
joins.forEach(join -> mIrc.join(mSession, join));
Java 7:
for (String join : joins) {
mIrc.join(mSession, join);
}
I have lots of for loops that could be "simplified" with lambdas, but is there really any advantage of using them? Would it improve their performance and readability?
EDIT
I'll also extend this question to longer methods. I know that you can't return or break the parent function from a lambda and this should also be taken into consideration when comparing them, but is there anything else to be considered?
The better practice is to use for-each. Besides violating the Keep It Simple, Stupid principle, the new-fangled forEach() has at least the following deficiencies:
Can't use non-final variables. So, code like the following can't be turned into a forEach lambda:
Object prev = null;
for(Object curr : list)
{
if( prev != null )
foo(prev, curr);
prev = curr;
}
Can't handle checked exceptions. Lambdas aren't actually forbidden from throwing checked exceptions, but common functional interfaces like Consumer don't declare any. Therefore, any code that throws checked exceptions must wrap them in try-catch or Throwables.propagate(). But even if you do that, it's not always clear what happens to the thrown exception. It could get swallowed somewhere in the guts of forEach()
Limited flow-control. A return in a lambda equals a continue in a for-each, but there is no equivalent to a break. It's also difficult to do things like return values, short circuit, or set flags (which would have alleviated things a bit, if it wasn't a violation of the no non-final variables rule). "This is not just an optimization, but critical when you consider that some sequences (like reading the lines in a file) may have side-effects, or you may have an infinite sequence."
Might execute in parallel, which is a horrible, horrible thing for all but the 0.1% of your code that needs to be optimized. Any parallel code has to be thought through (even if it doesn't use locks, volatiles, and other particularly nasty aspects of traditional multi-threaded execution). Any bug will be tough to find.
Might hurt performance, because the JIT can't optimize forEach()+lambda to the same extent as plain loops, especially now that lambdas are new. By "optimization" I do not mean the overhead of calling lambdas (which is small), but to the sophisticated analysis and transformation that the modern JIT compiler performs on running code.
If you do need parallelism, it is probably much faster and not much more difficult to use an ExecutorService. Streams are both automagical (read: don't know much about your problem) and use a specialized (read: inefficient for the general case) parallelization strategy (fork-join recursive decomposition).
Makes debugging more confusing, because of the nested call hierarchy and, god forbid, parallel execution. The debugger may have issues displaying variables from the surrounding code, and things like step-through may not work as expected.
Streams in general are more difficult to code, read, and debug. Actually, this is true of complex "fluent" APIs in general. The combination of complex single statements, heavy use of generics, and lack of intermediate variables conspire to produce confusing error messages and frustrate debugging. Instead of "this method doesn't have an overload for type X" you get an error message closer to "somewhere you messed up the types, but we don't know where or how." Similarly, you can't step through and examine things in a debugger as easily as when the code is broken into multiple statements, and intermediate values are saved to variables. Finally, reading the code and understanding the types and behavior at each stage of execution may be non-trivial.
Sticks out like a sore thumb. The Java language already has the for-each statement. Why replace it with a function call? Why encourage hiding side-effects somewhere in expressions? Why encourage unwieldy one-liners? Mixing regular for-each and new forEach willy-nilly is bad style. Code should speak in idioms (patterns that are quick to comprehend due to their repetition), and the fewer idioms are used the clearer the code is and less time is spent deciding which idiom to use (a big time-drain for perfectionists like myself!).
As you can see, I'm not a big fan of the forEach() except in cases when it makes sense.
Particularly offensive to me is the fact that Stream does not implement Iterable (despite actually having method iterator) and cannot be used in a for-each, only with a forEach(). I recommend casting Streams into Iterables with (Iterable<T>)stream::iterator. A better alternative is to use StreamEx which fixes a number of Stream API problems, including implementing Iterable.
That said, forEach() is useful for the following:
Atomically iterating over a synchronized list. Prior to this, a list generated with Collections.synchronizedList() was atomic with respect to things like get or set, but was not thread-safe when iterating.
Parallel execution (using an appropriate parallel stream). This saves you a few lines of code vs using an ExecutorService, if your problem matches the performance assumptions built into Streams and Spliterators.
Specific containers which, like the synchronized list, benefit from being in control of iteration (although this is largely theoretical unless people can bring up more examples)
Calling a single function more cleanly by using forEach() and a method reference argument (ie, list.forEach (obj::someMethod)). However, keep in mind the points on checked exceptions, more difficult debugging, and reducing the number of idioms you use when writing code.
Articles I used for reference:
Everything about Java 8
Iteration Inside and Out (as pointed out by another poster)
EDIT: Looks like some of the original proposals for lambdas (such as http://www.javac.info/closures-v06a.html Google Cache) solved some of the issues I mentioned (while adding their own complications, of course).
The advantage comes into account when the operations can be executed in parallel. (See http://java.dzone.com/articles/devoxx-2012-java-8-lambda-and - the section about internal and external iteration)
The main advantage from my point of view is that the implementation of what is to be done within the loop can be defined without having to decide if it will be executed in parallel or sequential
If you want your loop to be executed in parallel you could simply write
joins.parallelStream().forEach(join -> mIrc.join(mSession, join));
You will have to write some extra code for thread handling etc.
Note: For my answer I assumed joins implementing the java.util.Stream interface. If joins implements only the java.util.Iterable interface this is no longer true.
When reading this question one can get the impression, that Iterable#forEach in combination with lambda expressions is a shortcut/replacement for writing a traditional for-each loop. This is simply not true. This code from the OP:
joins.forEach(join -> mIrc.join(mSession, join));
is not intended as a shortcut for writing
for (String join : joins) {
mIrc.join(mSession, join);
}
and should certainly not be used in this way. Instead it is intended as a shortcut (although it is not exactly the same) for writing
joins.forEach(new Consumer<T>() {
#Override
public void accept(T join) {
mIrc.join(mSession, join);
}
});
And it is as a replacement for the following Java 7 code:
final Consumer<T> c = new Consumer<T>() {
#Override
public void accept(T join) {
mIrc.join(mSession, join);
}
};
for (T t : joins) {
c.accept(t);
}
Replacing the body of a loop with a functional interface, as in the examples above, makes your code more explicit: You are saying that (1) the body of the loop does not affect the surrounding code and control flow, and (2) the body of the loop may be replaced with a different implementation of the function, without affecting the surrounding code. Not being able to access non final variables of the outer scope is not a deficit of functions/lambdas, it is a feature that distinguishes the semantics of Iterable#forEach from the semantics of a traditional for-each loop. Once one gets used to the syntax of Iterable#forEach, it makes the code more readable, because you immediately get this additional information about the code.
Traditional for-each loops will certainly stay good practice (to avoid the overused term "best practice") in Java. But this doesn't mean, that Iterable#forEach should be considered bad practice or bad style. It is always good practice, to use the right tool for doing the job, and this includes mixing traditional for-each loops with Iterable#forEach, where it makes sense.
Since the downsides of Iterable#forEach have already been discussed in this thread, here are some reasons, why you might probably want to use Iterable#forEach:
To make your code more explicit: As described above, Iterable#forEach can make your code more explicit and readable in some situations.
To make your code more extensible and maintainable: Using a function as the body of a loop allows you to replace this function with different implementations (see Strategy Pattern). You could e.g. easily replace the lambda expression with a method call, that may be overwritten by sub-classes:
joins.forEach(getJoinStrategy());
Then you could provide default strategies using an enum, that implements the functional interface. This not only makes your code more extensible, it also increases maintainability because it decouples the loop implementation from the loop declaration.
To make your code more debuggable: Seperating the loop implementation from the declaration can also make debugging more easy, because you could have a specialized debug implementation, that prints out debug messages, without the need to clutter your main code with if(DEBUG)System.out.println(). The debug implementation could e.g. be a delegate, that decorates the actual function implementation.
To optimize performance-critical code: Contrary to some of the assertions in this thread, Iterable#forEach does already provide better performance than a traditional for-each loop, at least when using ArrayList and running Hotspot in "-client" mode. While this performance boost is small and negligible for most use cases, there are situations, where this extra performance can make a difference. E.g. library maintainers will certainly want to evaluate, if some of their existing loop implementations should be replaced with Iterable#forEach.
To back this statement up with facts, I have done some micro-benchmarks with Caliper. Here is the test code (latest Caliper from git is needed):
#VmOptions("-server")
public class Java8IterationBenchmarks {
public static class TestObject {
public int result;
}
public #Param({"100", "10000"}) int elementCount;
ArrayList<TestObject> list;
TestObject[] array;
#BeforeExperiment
public void setup(){
list = new ArrayList<>(elementCount);
for (int i = 0; i < elementCount; i++) {
list.add(new TestObject());
}
array = list.toArray(new TestObject[list.size()]);
}
#Benchmark
public void timeTraditionalForEach(int reps){
for (int i = 0; i < reps; i++) {
for (TestObject t : list) {
t.result++;
}
}
return;
}
#Benchmark
public void timeForEachAnonymousClass(int reps){
for (int i = 0; i < reps; i++) {
list.forEach(new Consumer<TestObject>() {
#Override
public void accept(TestObject t) {
t.result++;
}
});
}
return;
}
#Benchmark
public void timeForEachLambda(int reps){
for (int i = 0; i < reps; i++) {
list.forEach(t -> t.result++);
}
return;
}
#Benchmark
public void timeForEachOverArray(int reps){
for (int i = 0; i < reps; i++) {
for (TestObject t : array) {
t.result++;
}
}
}
}
And here are the results:
Results for -client
Results for -server
When running with "-client", Iterable#forEach outperforms the traditional for loop over an ArrayList, but is still slower than directly iterating over an array. When running with "-server", the performance of all approaches is about the same.
To provide optional support for parallel execution: It has already been said here, that the possibility to execute the functional interface of Iterable#forEach in parallel using streams, is certainly an important aspect. Since Collection#parallelStream() does not guarantee, that the loop is actually executed in parallel, one must consider this an optional feature. By iterating over your list with list.parallelStream().forEach(...);, you explicitly say: This loop supports parallel execution, but it does not depend on it. Again, this is a feature and not a deficit!
By moving the decision for parallel execution away from your actual loop implementation, you allow optional optimization of your code, without affecting the code itself, which is a good thing. Also, if the default parallel stream implementation does not fit your needs, no one is preventing you from providing your own implementation. You could e.g. provide an optimized collection depending on the underlying operating system, on the size of the collection, on the number of cores, and on some preference settings:
public abstract class MyOptimizedCollection<E> implements Collection<E>{
private enum OperatingSystem{
LINUX, WINDOWS, ANDROID
}
private OperatingSystem operatingSystem = OperatingSystem.WINDOWS;
private int numberOfCores = Runtime.getRuntime().availableProcessors();
private Collection<E> delegate;
#Override
public Stream<E> parallelStream() {
if (!System.getProperty("parallelSupport").equals("true")) {
return this.delegate.stream();
}
switch (operatingSystem) {
case WINDOWS:
if (numberOfCores > 3 && delegate.size() > 10000) {
return this.delegate.parallelStream();
}else{
return this.delegate.stream();
}
case LINUX:
return SomeVerySpecialStreamImplementation.stream(this.delegate.spliterator());
case ANDROID:
default:
return this.delegate.stream();
}
}
}
The nice thing here is, that your loop implementation doesn't need to know or care about these details.
forEach() can be implemented to be faster than for-each loop, because the iterable knows the best way to iterate its elements, as opposed to the standard iterator way. So the difference is loop internally or loop externally.
For example ArrayList.forEach(action) may be simply implemented as
for(int i=0; i<size; i++)
action.accept(elements[i])
as opposed to the for-each loop which requires a lot of scaffolding
Iterator iter = list.iterator();
while(iter.hasNext())
Object next = iter.next();
do something with `next`
However, we also need to account for two overhead costs by using forEach(), one is making the lambda object, the other is invoking the lambda method. They are probably not significant.
see also http://journal.stuffwithstuff.com/2013/01/13/iteration-inside-and-out/ for comparing internal/external iterations for different use cases.
TL;DR: List.stream().forEach() was the fastest.
I felt I should add my results from benchmarking iteration.
I took a very simple approach (no benchmarking frameworks) and benchmarked 5 different methods:
classic for
classic foreach
List.forEach()
List.stream().forEach()
List.parallelStream().forEach
the testing procedure and parameters
private List<Integer> list;
private final int size = 1_000_000;
public MyClass(){
list = new ArrayList<>();
Random rand = new Random();
for (int i = 0; i < size; ++i) {
list.add(rand.nextInt(size * 50));
}
}
private void doIt(Integer i) {
i *= 2; //so it won't get JITed out
}
The list in this class shall be iterated over and have some doIt(Integer i) applied to all it's members, each time via a different method.
in the Main class I run the tested method three times to warm up the JVM. I then run the test method 1000 times summing the time it takes for each iteration method (using System.nanoTime()). After that's done i divide that sum by 1000 and that's the result, average time.
example:
myClass.fored();
myClass.fored();
myClass.fored();
for (int i = 0; i < reps; ++i) {
begin = System.nanoTime();
myClass.fored();
end = System.nanoTime();
nanoSum += end - begin;
}
System.out.println(nanoSum / reps);
I ran this on a i5 4 core CPU, with java version 1.8.0_05
classic for
for(int i = 0, l = list.size(); i < l; ++i) {
doIt(list.get(i));
}
execution time: 4.21 ms
classic foreach
for(Integer i : list) {
doIt(i);
}
execution time: 5.95 ms
List.forEach()
list.forEach((i) -> doIt(i));
execution time: 3.11 ms
List.stream().forEach()
list.stream().forEach((i) -> doIt(i));
execution time: 2.79 ms
List.parallelStream().forEach
list.parallelStream().forEach((i) -> doIt(i));
execution time: 3.6 ms
I feel that I need to extend my comment a bit...
About paradigm\style
That's probably the most notable aspect. FP became popular due to what you can get avoiding side-effects. I won't delve deep into what pros\cons you can get from this, since this is not related to the question.
However, I will say that the iteration using Iterable.forEach is inspired by FP and rather result of bringing more FP to Java (ironically, I'd say that there is no much use for forEach in pure FP, since it does nothing except introducing side-effects).
In the end I would say that it is rather a matter of taste\style\paradigm you are currently writing in.
About parallelism.
From performance point of view there is no promised notable benefits from using Iterable.forEach over foreach(...).
According to official docs on Iterable.forEach :
Performs the given action on the contents of the Iterable, in the
order elements occur when iterating, until all elements have been
processed or the action throws an exception.
... i.e. docs pretty much clear that there will be no implicit parallelism. Adding one would be LSP violation.
Now, there are "parallell collections" that are promised in Java 8, but to work with those you need to me more explicit and put some extra care to use them (see mschenk74's answer for example).
BTW: in this case Stream.forEach will be used, and it doesn't guarantee that actual work will be done in parallell (depends on underlying collection).
UPDATE: might be not that obvious and a little stretched at a glance but there is another facet of style and readability perspective.
First of all - plain old forloops are plain and old. Everybody already knows them.
Second, and more important - you probably want to use Iterable.forEach only with one-liner lambdas. If "body" gets heavier - they tend to be not-that readable.
You have 2 options from here - use inner classes (yuck) or use plain old forloop.
People often gets annoyed when they see the same things (iteratins over collections) being done various vays/styles in the same codebase, and this seems to be the case.
Again, this might or might not be an issue. Depends on people working on code.
One of most upleasing functional forEach's limitations is lack of checked exceptions support.
One possible workaround is to replace terminal forEach with plain old foreach loop:
Stream<String> stream = Stream.of("", "1", "2", "3").filter(s -> !s.isEmpty());
Iterable<String> iterable = stream::iterator;
for (String s : iterable) {
fileWriter.append(s);
}
Here is list of most popular questions with other workarounds on checked exception handling within lambdas and streams:
Java 8 Lambda function that throws exception?
Java 8: Lambda-Streams, Filter by Method with Exception
How can I throw CHECKED exceptions from inside Java 8 streams?
Java 8: Mandatory checked exceptions handling in lambda expressions. Why mandatory, not optional?
The advantage of Java 1.8 forEach method over 1.7 Enhanced for loop is that while writing code you can focus on business logic only.
forEach method takes java.util.function.Consumer object as an argument, so It helps in having our business logic at a separate location that you can reuse it anytime.
Have look at below snippet,
Here I have created new Class that will override accept class method from Consumer Class,
where you can add additional functionility, More than Iteration..!!!!!!
class MyConsumer implements Consumer<Integer>{
#Override
public void accept(Integer o) {
System.out.println("Here you can also add your business logic that will work with Iteration and you can reuse it."+o);
}
}
public class ForEachConsumer {
public static void main(String[] args) {
// Creating simple ArrayList.
ArrayList<Integer> aList = new ArrayList<>();
for(int i=1;i<=10;i++) aList.add(i);
//Calling forEach with customized Iterator.
MyConsumer consumer = new MyConsumer();
aList.forEach(consumer);
// Using Lambda Expression for Consumer. (Functional Interface)
Consumer<Integer> lambda = (Integer o) ->{
System.out.println("Using Lambda Expression to iterate and do something else(BI).. "+o);
};
aList.forEach(lambda);
// Using Anonymous Inner Class.
aList.forEach(new Consumer<Integer>(){
#Override
public void accept(Integer o) {
System.out.println("Calling with Anonymous Inner Class "+o);
}
});
}
}
Related
Do lambda expressions have any use other than saving lines of code?
Are there any special features provided by lambdas which solved problems which weren't easy to solve? The typical usage I've seen is that instead of writing this:
Comparator<Developer> byName = new Comparator<Developer>() {
#Override
public int compare(Developer o1, Developer o2) {
return o1.getName().compareTo(o2.getName());
}
};
We can use a lambda expression to shorten the code:
Comparator<Developer> byName =
(Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName());
Lambda expressions do not change the set of problems you can solve with Java in general, but definitely make solving certain problems easier, just for the same reason we’re not programming in assembly language anymore. Removing redundant tasks from the programmer’s work makes life easier and allows to do things you wouldn’t even touch otherwise, just for the amount of code you would have to produce (manually).
But lambda expressions are not just saving lines of code. Lambda expressions allow you to define functions, something for which you could use anonymous inner classes as a workaround before, that’s why you can replace anonymous inner classes in these cases, but not in general.
Most notably, lambda expressions are defined independently to the functional interface they will be converted to, so there are no inherited members they could access, further, they can not access the instance of the type implementing the functional interface. Within a lambda expression, this and super have the same meaning as in the surrounding context, see also this answer. Also, you can not create new local variables shadowing local variables of the surrounding context. For the intended task of defining a function, this removes a lot of error sources, but it also implies that for other use cases, there might be anonymous inner classes which can not be converted to a lambda expression, even if implementing a functional interface.
Further, the construct new Type() { … } guarantees to produce a new distinct instance (as new always does). Anonymous inner class instances always keep a reference to their outer instance if created in a non-static context¹. In contrast, lambda expressions only capture a reference to this when needed, i.e. if they access this or a non-static member. And they produce instances of an intentionally unspecified identity, which allows the implementation to decide at runtime whether to reuse existing instances (see also “Does a lambda expression create an object on the heap every time it's executed?”).
These differences apply to your example. Your anonymous inner class construct will always produce a new instance, also it may capture a reference to the outer instance, whereas your (Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName()) is a non-capturing lambda expression that will evaluate to a singleton in typical implementations. Further, it doesn’t produce a .class file on your hard drive.
Given the differences regarding both, semantic and performance, lambda expressions may change the way programmers will solve certain problems in the future, of course, also due to the new APIs embracing ideas of functional programming utilizing the new language features. See also Java 8 lambda expression and first-class values.
¹ From JDK 1.1 to JDK 17. Starting with JDK 18, inner classes may not retain a reference to the outer instance if it is not used. For compatibility reasons, this requires the inner class not be serializable. This only applies if you (re)compile the inner class under JDK 18 or newer with target JDK 18 or newer. See also JDK-8271717
Programming languages are not for machines to execute.
They are for programmers to think in.
Languages are a conversation with a compiler to turn our thoughts into something a machine can execute. One of the chief complaints about Java from people who come to it from other languages (or leave it for other languages) used to be that it forces a certain mental model on the programmer (i.e. everything is a class).
I'm not going to weigh in on whether that's good or bad: everything is trade-offs. But Java 8 lambdas allow programmers to think in terms of functions, which is something you previously could not do in Java.
It's the same thing as a procedural programmer learning to think in terms of classes when they come to Java: you see them gradually move from classes that are glorified structs and have 'helper' classes with a bunch of static methods and move on to something that more closely resembles a rational OO design (mea culpa).
If you just think of them as a shorter way to express anonymous inner classes then you are probably not going to find them very impressive in the same way that the procedural programmer above probably didn't think classes were any great improvement.
Saving lines of code can be viewed as a new feature, if it enables you to write a substantial chunk of logic in a shorter and clearer manner, which takes less time for others to read and understand.
Without lambda expressions (and/or method references) Stream pipelines would have been much less readable.
Think, for example, how the following Stream pipeline would have looked like if you replaced each lambda expression with an anonymous class instance.
List<String> names =
people.stream()
.filter(p -> p.getAge() > 21)
.map(p -> p.getName())
.sorted((n1,n2) -> n1.compareToIgnoreCase(n2))
.collect(Collectors.toList());
It would be:
List<String> names =
people.stream()
.filter(new Predicate<Person>() {
#Override
public boolean test(Person p) {
return p.getAge() > 21;
}
})
.map(new Function<Person,String>() {
#Override
public String apply(Person p) {
return p.getName();
}
})
.sorted(new Comparator<String>() {
#Override
public int compare(String n1, String n2) {
return n1.compareToIgnoreCase(n2);
}
})
.collect(Collectors.toList());
This is much harder to write than the version with lambda expressions, and it's much more error prone. It's also harder to understand.
And this is a relatively short pipeline.
To make this readable without lambda expressions and method references, you would have had to define variables that hold the various functional interface instances being used here, which would have split the logic of the pipeline, making it harder to understand.
Internal iteration
When iterating Java Collections, most developers tend to get an element and then process it. This is, take that item out and then use it, or reinsert it, etc. With pre-8 versions of Java, you can implement an inner class and do something like:
numbers.forEach(new Consumer<Integer>() {
public void accept(Integer value) {
System.out.println(value);
}
});
Now with Java 8 you can do better and less verbose with:
numbers.forEach((Integer value) -> System.out.println(value));
or better
numbers.forEach(System.out::println);
Behaviors as arguments
Guess the following case:
public int sumAllEven(List<Integer> numbers) {
int total = 0;
for (int number : numbers) {
if (number % 2 == 0) {
total += number;
}
}
return total;
}
With Java 8 Predicate interface you can do better like so:
public int sumAll(List<Integer> numbers, Predicate<Integer> p) {
int total = 0;
for (int number : numbers) {
if (p.test(number)) {
total += number;
}
}
return total;
}
Calling it like:
sumAll(numbers, n -> n % 2 == 0);
Source: DZone - Why We Need Lambda Expressions in Java
There are many benefits of using lambdas instead of inner class following as below:
Make the code more compactly and expressive without introducing more language syntax semantics. you already gave an example in your question.
By using lambdas you are happy to programming with functional-style operations on streams of elements, such as map-reduce transformations on collections. see java.util.function & java.util.stream packages documentation.
There is no physical classes file generated for lambdas by compiler. Thus, it makes your delivered applications smaller. How Memory assigns to lambda?
The compiler will optimize lambda creation if the lambda doesn't access variables out of its scope, which means the lambda instance only create once by the JVM. for more details you can see #Holger's answer of the question Is method reference caching a good idea in Java 8?
.
Lambdas can implements multi marker interfaces besides the functional interface, but the anonymous inner classes can't implements more interfaces, for example:
// v--- create the lambda locally.
Consumer<Integer> action = (Consumer<Integer> & Serializable) it -> {/*TODO*/};
Lambdas are just syntactic sugar for anonymous classes.
Before lambdas, anonymous classes can be used to achieve the same thing. Every lambda expression can be converted to an anonymous class.
If you are using IntelliJ IDEA, it can do the conversion for you:
Put the cursor in the lambda
Press alt/option + enter
To answer your question, the matter of fact is lambdas don’t let you do anything that you couldn’t do prior to java-8, rather it enables you to write more concise code. The benefits of this, is that your code will be clearer and more flexible.
One thing I don't see mentioned yet is that a lambda lets you define functionality where it's used.
So if you have some simple selection function you don't need to put it in a separate place with a bunch of boilerplate, you just write a lambda that's concise and locally relevant.
Yes many advantages are there.
No need to define whole class we can pass implementation of function it self as reference.
Internally creation of class will create .class file while if you use lambda then class creation is avoided by compiler because in lambda you are passing function implementation instead of class.
Code re-usability is higher then before
And as you said code is shorter then normal implementation.
Function composition and higher order functions.
Lambda functions can be used as building blocks towards building "higher order functions" or performing "function composition". Lambda functions can be seen as reusable building blocks in this sense.
Example of Higher Order Function via lambda:
Function<IntUnaryOperator, IntUnaryOperator> twice = f -> f.andThen(f);
IntUnaryOperator plusThree = i -> i + 3;
var g = twice.apply(plusThree);
System.out.println(g.applyAsInt(7))
Example Function Composition
Predicate<String> startsWithA = (text) -> text.startsWith("A");
Predicate<String> endsWithX = (text) -> text.endsWith("x");
Predicate<String> startsWithAAndEndsWithX =
(text) -> startsWithA.test(text) && endsWithX.test(text);
String input = "A hardworking person must relax";
boolean result = startsWithAAndEndsWithX.test(input);
System.out.println(result);
One benefit not yet mentioned is my favorite: lambdas make deferred execution really easy to write.
Log4j2 uses this for example, where instead of passing a value to conditionally log (a value that may have been expensive to calculate), you can now pass a lambda to calculate that expensive value. The difference being that before, that value was being calculated every time whether it got used or not, whereas now with lambdas if your log level decides not to log that statement, then the lambda never gets called, and that expensive calculation never takes place -- a performance boost!
Could that be done without lambdas? Yes, by surrounding each log statement with if() checks, or using verbose anonymous class syntax, but at the cost of horrible code noise.
Similar examples abound. Lambdas are like having your cake and eating it too: all the efficiency of gnarly multi-line optimized code squeezed down into the visual elegance of one-liners.
Edit: As requested by commenter, an example:
Old way, where expensiveCalculation() always gets called regardless of whether this log statement will actually use it:
logger.trace("expensive value was {}", expensiveCalculation());
New lambda efficient way, where expensiveCalculation() call won't happen unless trace log level is enabled:
logger.trace("expensive value was {}", () -> expensiveCalculation());
What is considered idiomatic iteration of a Collection in Java 8, and why?
for (String foo : foos) {
String bar = bars.get(foo);
if (bar != null)
System.out.println(foo);
}
or
foos.forEach(foo -> {
String bar = bars.get(foo);
if (bar != null)
System.out.println(foo);
});
In the comment thread to this answer, user Bringer128 mentioned these questions regarding a similar issue in C#:
foreach vs someList.Foreach(){}
Generic lists: foreach or list.ForEach?
I would caution against applying the C# discussion to Java. The discussion is interesting, to be sure, and the issues are superficially similar. However, Java and C# are different languages and thus different considerations apply.
For example, this answer mentions that the C# foreach statement is preferable, because the compiler might be able to optimize the loop better in the future. This is not true of Java. In Java, the "enhanced for" loop is defined to be syntactic sugar for getting an Iterator and calling its hasNext and next methods repeatedly. This pretty much guarantees a minimum of two method calls per loop iteration (although there is a possibility for the JIT to inline small methods).
Another example is from this answer, which mentions that in C# it is legal for the delegate invoked by a list's ForEach method to modify the list that it's iterating. In Java there is a blanket prohibition of "interference" with the stream source for the Stream.forEach method, whereas for the enhanced-for loop, the behavior of modifying the underlying list (or whatever) is determined by the Iterator. Many are fail-fast and will throw ConcurrentModificationException if the underlying list is modified during iteration. Others will silently give unexpected results.
In any case, don't read the C# discussion and assume that similar reasoning applies to Java.
Now, to answer the question. :-)
I think it's too early to declare one style to be idiomatic or preferable to another at this point. Java 8 has just been released and very few people have much experience with it. Lambdas are new and unfamiliar, and this will make many programmers uncomfortable. They'll thus want to stick to their tried-and-true for-loops. That's perfectly sensible. In a few years, though, after everyone gets used to lambdas, it might be that for-loops will start to look distinctly old-fashioned. Time will tell.
(I think this happened with generics. When they were new, they were intimidating and scary, especially wildcards. Nowadays, though, non-generic code looks distinctly old-fashioned, and to me it has a musty odor about it.)
I have an early sense of how this might turn out. Of course, I might be wrong though.
I'd say that for short loops where the computation is fixed, such as the question posted initially:
for (String foo : foos)
System.out.println(foo);
it just doesn't matter. This could be rewritten as
foos.forEach(foo -> System.out.println(foo));
or even
foos.forEach(System.out::println);
But really, this code is so simple that it's hard to argue that one way is clearly better.
There are situations where the scales tip in one direction or another. If the loop body can throw a checked exception, a for-loop is clearly better. If the loop body is pluggable (e.g., the Consumer is passed in as a parameter) or if internal iteration has different semantics (e.g., locking of a synchronized list during the entire call to forEach) then the new forEach approach has the edge.
The updated example,
for (String foo : foos) {
String bar = bars.get(foo);
if (bar != null)
System.out.println(foo);
}
is a bit more complicated, but only slightly. I would not write this using a multi-line lambda:
foos.forEach(foo -> {
String bar = bars.get(foo);
if (bar != null)
System.out.println(foo);
});
This offers no advantage over the straight for-loop, in my opinion, and the different semantics of the lambda are signaled by the little arrow way up in the corner of the first line. However, (similar to Bringer128's answer) I would recast this from a big forEach block into a stream pipeline:
foos.stream()
.filter(foo -> bars.get(foo) != null)
.forEach(System.out::println)
I think the lambda/streams approach starts to show a bit of an advantage here, but only a bit, as this is still a really simple example. Using lambda/streams replaces some conditional control logic with a data filtering operation. This might make sense for some operations, but not for others.
The difference between the approaches starts to become clearer as things get more complicated. The simple examples are so simple that it's obvious what they do. Real-world examples can be considerably more complex. Consider this code from the method Class.getEnclosingMethod of the JDK (scroll to lines 1023-1052):
Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
// ...
for(Method m: enclosingCandidate.getDeclaredMethods()) {
if (m.getName().equals(enclosingInfo.getName()) ) {
Class<?>[] candidateParamClasses = m.getParameterTypes();
if (candidateParamClasses.length == parameterClasses.length) {
boolean matches = true;
for(int i = 0; i < candidateParamClasses.length; i++) {
if (!candidateParamClasses[i].equals(parameterClasses[i])) {
matches = false;
break;
}
}
if (matches) { // finally, check return type
if (m.getReturnType().equals(returnType) )
return m;
}
}
}
}
throw new InternalError("Enclosing method not found");
(Some security checks and comments have been omitted for the sake of the example.)
Here we have a couple nested for-loops with a couple levels of conditional logic and a boolean flag. Read through this code for a while and see if you can figure out what it does.
Using lambda and streams, this code can be rewritten as follows:
return Arrays.stream(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName()))
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.findFirst()
.orElseThrow(() -> new InternalError("Enclosing method not found");
What's going on in the classic version is that the loop control and conditional logic is all about searching a data structure for a match. It's a bit contorted because it breaks early out of the inner loop if it detects a non-match, but returns early from the method if it does find a match. But once you stare at this code long enough, you can see that it's searching for the first element that matches a series of criteria, and returns it; and if it doesn't find one, it throws an error. Once you realize that, the lambda/streams approach just pops right out. Not only is it a lot shorter, it's much easier to understand what it's doing.
There are certainly for-loops that will have weird conditions and side effects that can't be turned easily into streams. But there are a lot of for-loops that are just searching data structures, processing elements conditionally, returning the first match, or accumulating a collection of matches, or accumulating transformed elements. These operations naturally lend themselves to being rewritten into streams, and dare I say, in an idiomatic fashion.
In general the lambda form is more idiomatic for single-statement loops, whereas the non-lambda makes more sense for multi-statement loops. (This ignores composing into a more functional style if possible).
One more style you didn't mention is the method reference:
foos.forEach(System.out::println);
EDIT:
As you're looking for a more general answer; you might find that since lambdas are new in Java, the List.forEach method is less used in practice.
In response to "So why is non-lambda more idiomatic for multi-statement?", it's more the reverse, that multi-statement lambdas are not idiomatic in most languages. Lambdas tend to be used for composition, so if I was to take the example from your question and compose it into a functional style:
// Thanks to #skiwi for fixing this code
foos.stream().filter(foo -> bars.get(foo) != null).forEach(System.out::println);
In the above example, using multi-statement lambdas would make it harder to read rather than easier.
You should only be using the new stream/list's forEach if it really makes your code more concise, else stick with the old version, especially for code that gets executed linearly.
I would rewrite your statement to the following, which does make sense with streams:
foos.stream()
.filter(foo -> (bars.get(foo) != null))
.forEach(System.out::println);
This is a functional approach, that will:
Turn your List<String> into a Stream<String>.
Filter the objects such that you retain all elements of which bars.get(foo) is not null, which is of type Predicate<String>.
Then you call System.out::println on the Stream<String>, which resolves to bar -> System.out.println(bar), which is of type Consumer<String>.
So in more normal words:
Obtain a stream.
Filter out all unwanted elements, retain the wanted ones.
Consume all elements from the stream.
Which of the following is better practice in Java 8?
Java 8:
joins.forEach(join -> mIrc.join(mSession, join));
Java 7:
for (String join : joins) {
mIrc.join(mSession, join);
}
I have lots of for loops that could be "simplified" with lambdas, but is there really any advantage of using them? Would it improve their performance and readability?
EDIT
I'll also extend this question to longer methods. I know that you can't return or break the parent function from a lambda and this should also be taken into consideration when comparing them, but is there anything else to be considered?
The better practice is to use for-each. Besides violating the Keep It Simple, Stupid principle, the new-fangled forEach() has at least the following deficiencies:
Can't use non-final variables. So, code like the following can't be turned into a forEach lambda:
Object prev = null;
for(Object curr : list)
{
if( prev != null )
foo(prev, curr);
prev = curr;
}
Can't handle checked exceptions. Lambdas aren't actually forbidden from throwing checked exceptions, but common functional interfaces like Consumer don't declare any. Therefore, any code that throws checked exceptions must wrap them in try-catch or Throwables.propagate(). But even if you do that, it's not always clear what happens to the thrown exception. It could get swallowed somewhere in the guts of forEach()
Limited flow-control. A return in a lambda equals a continue in a for-each, but there is no equivalent to a break. It's also difficult to do things like return values, short circuit, or set flags (which would have alleviated things a bit, if it wasn't a violation of the no non-final variables rule). "This is not just an optimization, but critical when you consider that some sequences (like reading the lines in a file) may have side-effects, or you may have an infinite sequence."
Might execute in parallel, which is a horrible, horrible thing for all but the 0.1% of your code that needs to be optimized. Any parallel code has to be thought through (even if it doesn't use locks, volatiles, and other particularly nasty aspects of traditional multi-threaded execution). Any bug will be tough to find.
Might hurt performance, because the JIT can't optimize forEach()+lambda to the same extent as plain loops, especially now that lambdas are new. By "optimization" I do not mean the overhead of calling lambdas (which is small), but to the sophisticated analysis and transformation that the modern JIT compiler performs on running code.
If you do need parallelism, it is probably much faster and not much more difficult to use an ExecutorService. Streams are both automagical (read: don't know much about your problem) and use a specialized (read: inefficient for the general case) parallelization strategy (fork-join recursive decomposition).
Makes debugging more confusing, because of the nested call hierarchy and, god forbid, parallel execution. The debugger may have issues displaying variables from the surrounding code, and things like step-through may not work as expected.
Streams in general are more difficult to code, read, and debug. Actually, this is true of complex "fluent" APIs in general. The combination of complex single statements, heavy use of generics, and lack of intermediate variables conspire to produce confusing error messages and frustrate debugging. Instead of "this method doesn't have an overload for type X" you get an error message closer to "somewhere you messed up the types, but we don't know where or how." Similarly, you can't step through and examine things in a debugger as easily as when the code is broken into multiple statements, and intermediate values are saved to variables. Finally, reading the code and understanding the types and behavior at each stage of execution may be non-trivial.
Sticks out like a sore thumb. The Java language already has the for-each statement. Why replace it with a function call? Why encourage hiding side-effects somewhere in expressions? Why encourage unwieldy one-liners? Mixing regular for-each and new forEach willy-nilly is bad style. Code should speak in idioms (patterns that are quick to comprehend due to their repetition), and the fewer idioms are used the clearer the code is and less time is spent deciding which idiom to use (a big time-drain for perfectionists like myself!).
As you can see, I'm not a big fan of the forEach() except in cases when it makes sense.
Particularly offensive to me is the fact that Stream does not implement Iterable (despite actually having method iterator) and cannot be used in a for-each, only with a forEach(). I recommend casting Streams into Iterables with (Iterable<T>)stream::iterator. A better alternative is to use StreamEx which fixes a number of Stream API problems, including implementing Iterable.
That said, forEach() is useful for the following:
Atomically iterating over a synchronized list. Prior to this, a list generated with Collections.synchronizedList() was atomic with respect to things like get or set, but was not thread-safe when iterating.
Parallel execution (using an appropriate parallel stream). This saves you a few lines of code vs using an ExecutorService, if your problem matches the performance assumptions built into Streams and Spliterators.
Specific containers which, like the synchronized list, benefit from being in control of iteration (although this is largely theoretical unless people can bring up more examples)
Calling a single function more cleanly by using forEach() and a method reference argument (ie, list.forEach (obj::someMethod)). However, keep in mind the points on checked exceptions, more difficult debugging, and reducing the number of idioms you use when writing code.
Articles I used for reference:
Everything about Java 8
Iteration Inside and Out (as pointed out by another poster)
EDIT: Looks like some of the original proposals for lambdas (such as http://www.javac.info/closures-v06a.html Google Cache) solved some of the issues I mentioned (while adding their own complications, of course).
The advantage comes into account when the operations can be executed in parallel. (See http://java.dzone.com/articles/devoxx-2012-java-8-lambda-and - the section about internal and external iteration)
The main advantage from my point of view is that the implementation of what is to be done within the loop can be defined without having to decide if it will be executed in parallel or sequential
If you want your loop to be executed in parallel you could simply write
joins.parallelStream().forEach(join -> mIrc.join(mSession, join));
You will have to write some extra code for thread handling etc.
Note: For my answer I assumed joins implementing the java.util.Stream interface. If joins implements only the java.util.Iterable interface this is no longer true.
When reading this question one can get the impression, that Iterable#forEach in combination with lambda expressions is a shortcut/replacement for writing a traditional for-each loop. This is simply not true. This code from the OP:
joins.forEach(join -> mIrc.join(mSession, join));
is not intended as a shortcut for writing
for (String join : joins) {
mIrc.join(mSession, join);
}
and should certainly not be used in this way. Instead it is intended as a shortcut (although it is not exactly the same) for writing
joins.forEach(new Consumer<T>() {
#Override
public void accept(T join) {
mIrc.join(mSession, join);
}
});
And it is as a replacement for the following Java 7 code:
final Consumer<T> c = new Consumer<T>() {
#Override
public void accept(T join) {
mIrc.join(mSession, join);
}
};
for (T t : joins) {
c.accept(t);
}
Replacing the body of a loop with a functional interface, as in the examples above, makes your code more explicit: You are saying that (1) the body of the loop does not affect the surrounding code and control flow, and (2) the body of the loop may be replaced with a different implementation of the function, without affecting the surrounding code. Not being able to access non final variables of the outer scope is not a deficit of functions/lambdas, it is a feature that distinguishes the semantics of Iterable#forEach from the semantics of a traditional for-each loop. Once one gets used to the syntax of Iterable#forEach, it makes the code more readable, because you immediately get this additional information about the code.
Traditional for-each loops will certainly stay good practice (to avoid the overused term "best practice") in Java. But this doesn't mean, that Iterable#forEach should be considered bad practice or bad style. It is always good practice, to use the right tool for doing the job, and this includes mixing traditional for-each loops with Iterable#forEach, where it makes sense.
Since the downsides of Iterable#forEach have already been discussed in this thread, here are some reasons, why you might probably want to use Iterable#forEach:
To make your code more explicit: As described above, Iterable#forEach can make your code more explicit and readable in some situations.
To make your code more extensible and maintainable: Using a function as the body of a loop allows you to replace this function with different implementations (see Strategy Pattern). You could e.g. easily replace the lambda expression with a method call, that may be overwritten by sub-classes:
joins.forEach(getJoinStrategy());
Then you could provide default strategies using an enum, that implements the functional interface. This not only makes your code more extensible, it also increases maintainability because it decouples the loop implementation from the loop declaration.
To make your code more debuggable: Seperating the loop implementation from the declaration can also make debugging more easy, because you could have a specialized debug implementation, that prints out debug messages, without the need to clutter your main code with if(DEBUG)System.out.println(). The debug implementation could e.g. be a delegate, that decorates the actual function implementation.
To optimize performance-critical code: Contrary to some of the assertions in this thread, Iterable#forEach does already provide better performance than a traditional for-each loop, at least when using ArrayList and running Hotspot in "-client" mode. While this performance boost is small and negligible for most use cases, there are situations, where this extra performance can make a difference. E.g. library maintainers will certainly want to evaluate, if some of their existing loop implementations should be replaced with Iterable#forEach.
To back this statement up with facts, I have done some micro-benchmarks with Caliper. Here is the test code (latest Caliper from git is needed):
#VmOptions("-server")
public class Java8IterationBenchmarks {
public static class TestObject {
public int result;
}
public #Param({"100", "10000"}) int elementCount;
ArrayList<TestObject> list;
TestObject[] array;
#BeforeExperiment
public void setup(){
list = new ArrayList<>(elementCount);
for (int i = 0; i < elementCount; i++) {
list.add(new TestObject());
}
array = list.toArray(new TestObject[list.size()]);
}
#Benchmark
public void timeTraditionalForEach(int reps){
for (int i = 0; i < reps; i++) {
for (TestObject t : list) {
t.result++;
}
}
return;
}
#Benchmark
public void timeForEachAnonymousClass(int reps){
for (int i = 0; i < reps; i++) {
list.forEach(new Consumer<TestObject>() {
#Override
public void accept(TestObject t) {
t.result++;
}
});
}
return;
}
#Benchmark
public void timeForEachLambda(int reps){
for (int i = 0; i < reps; i++) {
list.forEach(t -> t.result++);
}
return;
}
#Benchmark
public void timeForEachOverArray(int reps){
for (int i = 0; i < reps; i++) {
for (TestObject t : array) {
t.result++;
}
}
}
}
And here are the results:
Results for -client
Results for -server
When running with "-client", Iterable#forEach outperforms the traditional for loop over an ArrayList, but is still slower than directly iterating over an array. When running with "-server", the performance of all approaches is about the same.
To provide optional support for parallel execution: It has already been said here, that the possibility to execute the functional interface of Iterable#forEach in parallel using streams, is certainly an important aspect. Since Collection#parallelStream() does not guarantee, that the loop is actually executed in parallel, one must consider this an optional feature. By iterating over your list with list.parallelStream().forEach(...);, you explicitly say: This loop supports parallel execution, but it does not depend on it. Again, this is a feature and not a deficit!
By moving the decision for parallel execution away from your actual loop implementation, you allow optional optimization of your code, without affecting the code itself, which is a good thing. Also, if the default parallel stream implementation does not fit your needs, no one is preventing you from providing your own implementation. You could e.g. provide an optimized collection depending on the underlying operating system, on the size of the collection, on the number of cores, and on some preference settings:
public abstract class MyOptimizedCollection<E> implements Collection<E>{
private enum OperatingSystem{
LINUX, WINDOWS, ANDROID
}
private OperatingSystem operatingSystem = OperatingSystem.WINDOWS;
private int numberOfCores = Runtime.getRuntime().availableProcessors();
private Collection<E> delegate;
#Override
public Stream<E> parallelStream() {
if (!System.getProperty("parallelSupport").equals("true")) {
return this.delegate.stream();
}
switch (operatingSystem) {
case WINDOWS:
if (numberOfCores > 3 && delegate.size() > 10000) {
return this.delegate.parallelStream();
}else{
return this.delegate.stream();
}
case LINUX:
return SomeVerySpecialStreamImplementation.stream(this.delegate.spliterator());
case ANDROID:
default:
return this.delegate.stream();
}
}
}
The nice thing here is, that your loop implementation doesn't need to know or care about these details.
forEach() can be implemented to be faster than for-each loop, because the iterable knows the best way to iterate its elements, as opposed to the standard iterator way. So the difference is loop internally or loop externally.
For example ArrayList.forEach(action) may be simply implemented as
for(int i=0; i<size; i++)
action.accept(elements[i])
as opposed to the for-each loop which requires a lot of scaffolding
Iterator iter = list.iterator();
while(iter.hasNext())
Object next = iter.next();
do something with `next`
However, we also need to account for two overhead costs by using forEach(), one is making the lambda object, the other is invoking the lambda method. They are probably not significant.
see also http://journal.stuffwithstuff.com/2013/01/13/iteration-inside-and-out/ for comparing internal/external iterations for different use cases.
TL;DR: List.stream().forEach() was the fastest.
I felt I should add my results from benchmarking iteration.
I took a very simple approach (no benchmarking frameworks) and benchmarked 5 different methods:
classic for
classic foreach
List.forEach()
List.stream().forEach()
List.parallelStream().forEach
the testing procedure and parameters
private List<Integer> list;
private final int size = 1_000_000;
public MyClass(){
list = new ArrayList<>();
Random rand = new Random();
for (int i = 0; i < size; ++i) {
list.add(rand.nextInt(size * 50));
}
}
private void doIt(Integer i) {
i *= 2; //so it won't get JITed out
}
The list in this class shall be iterated over and have some doIt(Integer i) applied to all it's members, each time via a different method.
in the Main class I run the tested method three times to warm up the JVM. I then run the test method 1000 times summing the time it takes for each iteration method (using System.nanoTime()). After that's done i divide that sum by 1000 and that's the result, average time.
example:
myClass.fored();
myClass.fored();
myClass.fored();
for (int i = 0; i < reps; ++i) {
begin = System.nanoTime();
myClass.fored();
end = System.nanoTime();
nanoSum += end - begin;
}
System.out.println(nanoSum / reps);
I ran this on a i5 4 core CPU, with java version 1.8.0_05
classic for
for(int i = 0, l = list.size(); i < l; ++i) {
doIt(list.get(i));
}
execution time: 4.21 ms
classic foreach
for(Integer i : list) {
doIt(i);
}
execution time: 5.95 ms
List.forEach()
list.forEach((i) -> doIt(i));
execution time: 3.11 ms
List.stream().forEach()
list.stream().forEach((i) -> doIt(i));
execution time: 2.79 ms
List.parallelStream().forEach
list.parallelStream().forEach((i) -> doIt(i));
execution time: 3.6 ms
I feel that I need to extend my comment a bit...
About paradigm\style
That's probably the most notable aspect. FP became popular due to what you can get avoiding side-effects. I won't delve deep into what pros\cons you can get from this, since this is not related to the question.
However, I will say that the iteration using Iterable.forEach is inspired by FP and rather result of bringing more FP to Java (ironically, I'd say that there is no much use for forEach in pure FP, since it does nothing except introducing side-effects).
In the end I would say that it is rather a matter of taste\style\paradigm you are currently writing in.
About parallelism.
From performance point of view there is no promised notable benefits from using Iterable.forEach over foreach(...).
According to official docs on Iterable.forEach :
Performs the given action on the contents of the Iterable, in the
order elements occur when iterating, until all elements have been
processed or the action throws an exception.
... i.e. docs pretty much clear that there will be no implicit parallelism. Adding one would be LSP violation.
Now, there are "parallell collections" that are promised in Java 8, but to work with those you need to me more explicit and put some extra care to use them (see mschenk74's answer for example).
BTW: in this case Stream.forEach will be used, and it doesn't guarantee that actual work will be done in parallell (depends on underlying collection).
UPDATE: might be not that obvious and a little stretched at a glance but there is another facet of style and readability perspective.
First of all - plain old forloops are plain and old. Everybody already knows them.
Second, and more important - you probably want to use Iterable.forEach only with one-liner lambdas. If "body" gets heavier - they tend to be not-that readable.
You have 2 options from here - use inner classes (yuck) or use plain old forloop.
People often gets annoyed when they see the same things (iteratins over collections) being done various vays/styles in the same codebase, and this seems to be the case.
Again, this might or might not be an issue. Depends on people working on code.
One of most upleasing functional forEach's limitations is lack of checked exceptions support.
One possible workaround is to replace terminal forEach with plain old foreach loop:
Stream<String> stream = Stream.of("", "1", "2", "3").filter(s -> !s.isEmpty());
Iterable<String> iterable = stream::iterator;
for (String s : iterable) {
fileWriter.append(s);
}
Here is list of most popular questions with other workarounds on checked exception handling within lambdas and streams:
Java 8 Lambda function that throws exception?
Java 8: Lambda-Streams, Filter by Method with Exception
How can I throw CHECKED exceptions from inside Java 8 streams?
Java 8: Mandatory checked exceptions handling in lambda expressions. Why mandatory, not optional?
The advantage of Java 1.8 forEach method over 1.7 Enhanced for loop is that while writing code you can focus on business logic only.
forEach method takes java.util.function.Consumer object as an argument, so It helps in having our business logic at a separate location that you can reuse it anytime.
Have look at below snippet,
Here I have created new Class that will override accept class method from Consumer Class,
where you can add additional functionility, More than Iteration..!!!!!!
class MyConsumer implements Consumer<Integer>{
#Override
public void accept(Integer o) {
System.out.println("Here you can also add your business logic that will work with Iteration and you can reuse it."+o);
}
}
public class ForEachConsumer {
public static void main(String[] args) {
// Creating simple ArrayList.
ArrayList<Integer> aList = new ArrayList<>();
for(int i=1;i<=10;i++) aList.add(i);
//Calling forEach with customized Iterator.
MyConsumer consumer = new MyConsumer();
aList.forEach(consumer);
// Using Lambda Expression for Consumer. (Functional Interface)
Consumer<Integer> lambda = (Integer o) ->{
System.out.println("Using Lambda Expression to iterate and do something else(BI).. "+o);
};
aList.forEach(lambda);
// Using Anonymous Inner Class.
aList.forEach(new Consumer<Integer>(){
#Override
public void accept(Integer o) {
System.out.println("Calling with Anonymous Inner Class "+o);
}
});
}
}
Recent events on the blogosphere have indicated that a possible performance problem with Scala is its use of closures to implement for.
What are the reasons for this design decision, as opposed to a C or Java-style "primitive for" - that is one which will be turned into a simple loop?
(I'm making a distinction between Java's for and its "foreach" construct here, as the latter involves an implicit Iterator).
More detail, following up from Peter. This bit of Scala:
object ScratchFor {
def main(args : Array[String]) : Unit = {
for (val s <- args) {
println(s)
}
}
}
creates 3 classes: ScratchFor$$anonfun$main$1.class ScratchFor$.class ScratchFor.class
ScratchFor::main just forwards to the companion object, ScratchFor$.MODULE$::main which spins up an ScratchFor$$anonfun$main$1 (which is an implementation of AbstractFunction1).
It's in the apply() method of this anonymous inner impl of AbstractFunction1 that the actual code lives, which is effectively the loop body.
I don't see HotSpot being able to rewrite this into a simple loop. Happy to be proved wrong on this, though.
Traditional for loops are clumsy, verbose and error-prone. I think it is proof enough of this that "for-each" loops where added to Java, C# and C++, but if you want more details you may check item 46 of Effective Java.
Now, for-each loops are still much faster than Scala for-comprehension, but they are also much less powerful (and more clumsy) because they cannot return values. If you want to transform or filter a collection (or do both to a group of collections), you'll still have to handle all the mechanical details of constructing the result collection in addition to computing the values. Not to mention it inevitably uses some mutable state.
Finally, even though for-each loops are adequate enough for collections, they are not suited to other monadic classes (of which collections are a subset of).
So Scala has a general method which takes care of all of the above. Yes, it is slower, but the goal is to have the compiler effectively optimise it well enough so that this doesn't become a hindrance (and, of course, JIT could help here as well).
That has not been accomplished to this date, but -optimise has reduced a lot of ground between common for-each loops and for-comprehensions on the latest versions of Scala. If performance is essential, you can always use while or tail recursion.
Now, it would be possibly for Scala to have common for loops or for-each loops as special cases specifically targeted at performance issues (since for-comprehensions can do everything they do). However, that violates two principles that guide Scala's design:
Reduce complexity. Yes, contrary to what some say, that is a design goal, and special cases that serve no other purpose other than optimise performance -- even though a workable solution exists for performance cases -- would needlessly increase the complexity of the language.
Scalability. This is in the sense that the use can scale the language for any size of problem by writing libraries. The point here is that having the compiler optimise one particular class, such as Range, would make it impossible for the user to create a replacement class that would perform just as well.
The for comprehension in Scala is a powerful general-purpose looping and pattern-matching construct. Look at what it can do:
case class Person(first: String, last: String) {}
val people = List(Person("Isaac","Newton"), Person("Michael","Jordan"))
val lastfirst = for (Person(f,l) <- people) yield l+", "+f
for (n <- lastfirst) println(n)
The second case looks pretty straightforward--take each item in a collection and print it. But the first takes apart a list containing a custom data structure and transforms it into a different collection type!
The first for there highlights only a small portion of the capability of the construct; it is both extremely powerful and extremely general. In order to maintain this power, the for must be able to turn into something very general, which means closures. Then the question is: do you also introduce special cases that operate on known collections in simple ways with improved performance? The answer thus far has been mostly no, instead preferring solutions that optimize the general closure-taking methods that for turns into.
Whether this is useful for you in particular depends on whether you are using the general capabilities a lot (in which case you will be glad) or not (in which case you may wish progress was faster).
Still, try -optimize. It often usefully speeds up simple for-comprehensions these days.
The for-comprehension is much more than a simple loop.
If you need an imperative loop, use while. If you want to write performant code in Scala, you need to know this. Just like you have to know about language implementation when you want to write fast code in every other language.
So, since the for-comprehension is not a simple loop, I hope you understand that it's not compiled down to a simple loop.
I would assume using a closure is a general solution. A more optimal solution in some cases would be to "inline" the closure as a loop and eliminate the need to create an object. Perhaps the Scala designers feel the JIT should do this, rather having the compiler do this.
Let's say in Java this is the same as writing
public static void main(String... args) {
for_loop(args, new Function<String>() {
public void apply(String s) {
System.out.println(s);
}
});
}
interface Function<T> {
void apply(T s);
}
public static <T> void for_loop(T... ts, Function<T> tFunc) {
for(T t: ts) tFunc.apply(t);
}
This is fairly easy to inline (if you're a human). What is surprising is that Scala doesn't have an intrinsic to perform the optimisation to eliminate the need for a new object. Certainly the JIT could do it in theory, but in practise, it might be a while before it handles this specific case.
I'm surprised that no one has mentioned one of the pitfalls you can get into if for does not create a closure.
In Python for example:
ls = [None] * 3
for i in [0, 1, 2]:
ls[i] = lambda: i
print(ls[0]())
print(ls[1]())
print(ls[2]())
This prints 2 2 2, because i has a longer lifetime than the for loop. I run into this trap all the time in Python and R.
So even in the very simplest of cases, it is important for for in Scala to be implemented using an anonymous function, because it creates an environment to store variables.
Why was this loop introduced in java?Is it a java creation? What is its purpose(increases memory/cpu utilisation efficiency)?
Why was this loop introduced in java?
It's just to ease looping over generic collections and arrays. Instead of
for (int i = 0; i < strings.length; i++) {
String string = strings[i];
// ...
}
you can just do
for (String string : strings) {
// ...
}
which makes the code more readable and better maintainable.
Is it a java creation?
No, it existed in other languages long before Java. Java was relatively late in implementing it.
What is its purpose?
See the first answer.
To learn more about it, checkout the Sun guide on the subject.
Update: this does not mean that it makes the other kinds of loops superfluous. the for loop using index is still useful if you'd like to maintain a loop counter for other purposes than getting the item by index. The for loop using an iterator is still useful if you'd like to remove or change elements of the collection itself inside a loop.
It masks the use of iterators, which are heavy and clumsy to use. There are many, many instances where you just want to iterate over a collection without working about its index. The java foreach structure makes this possible.
Please see Foreach:
For each (or foreach) is a computer
language idiom for traversing items in
a collection. Foreach is usually used
in place of a standard for statement.
Unlike other for loop constructs,
however, foreach loops 1 usually
maintain no explicit counter: they
essentially say "do this to everything
in this set", rather than "do this x
times". This avoids potential
off-by-one errors and makes code
simpler to read. In object-oriented
languages an iterator, even if
implicit, is often used as the means
of traversal.
Several languages, including Python,
have only a foreach loop, requiring
explicit counting to achieve
"standard" for behavior.
And specifically the section on Java:
A foreach-construct was introduced in JDK 5.0. Official sources use several names for the construct. It is referred to as the "Enhanced for Loop" the "For-Each Loop" and the "foreach statement".
It's really just Java's imitation of a functional construct that's been around much longer, it's called map. The reason for implementing it is that it is common to make a loop that simply performs an action to every element of a container without regard to it's index. Java's for(element : container) { doSomethingWith(element); } syntax is just a cleaner way to do it than the alternatives, which are either to make a for loop with an index
for(int i=0; i<container.size(); ++i) { doSomethingWith(container.at(i)); }
which is longer and creates a needless index variable, or to do a loop with an iterator
Iterator it = container.iterator();
while(it.hasNext()) { doSomethingWith(it.next()); }
which is also longer. This loop is essentially what the for( : ) {} loop gets compiled as, although there may be some slight differences (I haven't actually seen the bytecode).
It is plain "Syntactic sugar"
Dont think there is any efficiency improvement.
Java community wanted the language to be a bit modernized, competing with C# and Ruby..