By design the for each variable 'x' (in this case) is not meant to be assigned to. I'm surprised that it even compiles fine.
String[] currentState = new String[answer.length()];
for (String x : currentState) {
x = "_"; // x is not a reference to some element of currentState
}
The following code maybe shows what you're in effect are doing. Note that this is not how enumerations work but it exemplifies why you can't assign 'x'. It's a copy of the element at location 'i'. (Edit: note that the element is a reference type, as such it's a copy of that reference, assignment to that copy does not update the same memory location i.e. the element at location 'i')
String[] currentState = new String[answer.length()];
for (int i = 0; i < answer.length(); i++) {
String x = currentState[i];
x = "_";
}
Answer from John Leidegren on Stack Overflowforeach - Understanding for each loop in Java - Stack Overflow
Java 8 Iterable.forEach() vs foreach loop - Stack Overflow
When to use for-each Loop, while loop, Iterator Object?
[Java] Simple explanation of for each loops
Videos
By design the for each variable 'x' (in this case) is not meant to be assigned to. I'm surprised that it even compiles fine.
String[] currentState = new String[answer.length()];
for (String x : currentState) {
x = "_"; // x is not a reference to some element of currentState
}
The following code maybe shows what you're in effect are doing. Note that this is not how enumerations work but it exemplifies why you can't assign 'x'. It's a copy of the element at location 'i'. (Edit: note that the element is a reference type, as such it's a copy of that reference, assignment to that copy does not update the same memory location i.e. the element at location 'i')
String[] currentState = new String[answer.length()];
for (int i = 0; i < answer.length(); i++) {
String x = currentState[i];
x = "_";
}
Original code:
String currentState = new String[answer.length()];
for(String x : currentState)
{
x = "_";
}
Rewritten code:
String currentState = new String[answer.length()];
for(int i = 0; i < currentState.length; i++)
{
String x;
x = currentState[i];
x = "_";
}
How I would write the code:
String currentState = new String[answer.length()];
for(final String x : currentState)
{
x = "_"; // compiler error
}
Rewritten code with the error:
String currentState = new String[answer.length()];
for(int i = 0; i < currentState.length; i++)
{
final String x;
x = currentState[i];
x = "_"; // compiler error
}
Making the variables final highlights when you do things like this (it is a common beginner mistake). Try to make all of your variables final (instance, class, arguments, exceptions in catch. etc...) - only make them non-final if you really have to change them. You should find that 90%-95% of your variables are final (beginners will wind up with 20%-50% when they start doing this).
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
Consumerdon't declare any. Therefore, any code that throws checked exceptions must wrap them intry-catchorThrowables.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 offorEach()Limited flow-control. A
returnin a lambda equals acontinuein a for-each, but there is no equivalent to abreak. 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.
Basically in the title. I have a hard time deciding which one to use to iterate over a collection. I am pretty sure that for-each is for definite iteration (i.e. when you know exactly how many elements you want to iterate across), while is for indefinite iteration (i.e. you do not know where the element that you're looking for is in the collection), and I have absolutely no idea about when you should use an Iterator Object. Could somebody please be kind enough to explain the difference between the three?
Hi, every example I see of for each loops I see confuses me. I know for for loops it is: for(begining counter; do while counter is less, greater or equal to n; increase or decrease counter) . I was hoping someone could help explain how for each loops work and there applications instead of for loops. Sorry if this is a basic question, other answers I found in the java documentation and on stackoverflow didn't seem to help me.
Edit: I understand now! Thank you guys so much!