How does a for-each loop work? [duplicate] - java

This question already has answers here:
How does the Java 'for each' loop work?
(29 answers)
Closed 7 years ago.
How does a for-each loop works when it calls a method, either recursively or a different method?
Example:
for(String permutation : permute(remaining))
{
// Concatenate the first character with the permutations of the remaining chars
set.add(chars.charAt(i) + permutation);
}
By the way the method permute takes in a String and returns a set.
Thank you.

According to the Java Language Specification for the enhanced for statement, the expression:
for ( FormalParameter : Expression ) Statement
Is executed as follows:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
VariableModifiersopt TargetType Identifier =
(TargetType) #i.next();
Statement
}
Thus, the Expression (which must be of type Iterable) only has its iterator() method called once.

Calls it once, stores the result, does foreach.
Like this:
Collection<String> temp = permute(remaining);
for(String permutation : temp) {
...
}
Edit: If this is recursive, it really makes no difference. Every layer of recursion simply has its own scope, and thus its own "temp" variable. Thus the permute function will recurse to the lowest level, then each higher level will do its completely separate foreach loop successively.

If we compile this Test
class Test {
public static void main(String[] args) throws Exception {
Set<String> set = new HashSet<>();
for (String s : set) {
}
}
}
and decompile Test.class with JAD we will see that javac replaced for-each with this code
Set set = new HashSet();
String s;
for(Iterator iterator = set.iterator(); iterator.hasNext();)
s = (String)iterator.next();

Foreach loop works on any class that implements the Iterable interface, and is only syntax sugar for calling hasNext() and next() on an Iterator. Same thread same loop and the function is called once.

In your example, the result of permute(remaining) is evaluated before one enters into the loop. While the enhanced for loop is really nothing more than syntactic sugar for iterators, it still follows the same principles as other loops would - it has to have a set to operate with before it can do anything else.
A simpler example would be something like this:
while(input.hasNext())
That's something you may see in projects that read in an indefinite amount of lines. The expression input.hasNext() has to be evaluated first, then you may loop.

Related

Using synchronizedList with for loop and adding items inside it

I'm using
Collections.synchronizedList(new ArrayList<T>())
part of the code is:
list = Collections.synchronizedList(new ArrayList<T>());
public void add(T arg) {
int i;
synchronized (list) {
for (i = 0; i < list.size(); i++) {
T arg2 = list.get(i);
if (arg2.compareTo(arg) < 0) {
list.add(i, arg);
break;
}
}
Is it right that for loop is actually using iterator and therefore I must wrap the for with synchronized?
Is it thread-safe to use synchronized and make addition inside it like I did here?
I'm sorry if these questions are very basic, I'm new to the subject and didn't find answers on the internet.
Thank you!!
Is it right that for loop is actually using iterator and therefore I must wrap the for with synchronized?
There are two parts to your question.
Firstly, no, you're not using an iterator here, this is a basic for loop.
The enhanced for loop is the for loop which uses an iterator:
for (T element : list) { ... }
You can see in the language spec how this uses the iterator - search for where it says "The enhanced for statement is equivalent to a basic for statement of the form".
Secondly, even though you're not using an iterator, you do need synchronized. The two are orthogonal.
You are doing multiple operations (the size, the get and the add), with dependencies between them. You need to make sure that no other thread interferes with your logic:
the get depends on the size, since you don't want to try to get an element with index >= size, for instance;
the add depends on the get, since you're apparently trying to ensure the list elements are ordered. If another thread could sneak in and change the element after you get it, you might insert the new element in the wrong place.
You correctly avoid this potential interference this through synchronization over list, and creating the synchronizedList in such a way that nothing other than the synchronizedList can get direct access to the underlying list.
If your arg2.compareTo(arg) never return 0 (zero) you can use TreeSet. Will be much more simple:
set = Collections.synchronizedSet(new TreeSet<T>());
public void add(T arg) {
set.add(arg);
}
If you need hold same items (compareTo returns 0) then use the list:
list = new ArrayList<T>();
public void add(T arg) {
synchronized (list) {
int index = Collections.binarySearch(list, arg);
list.add(index, arg);
}
}
First and second cases complexity will be log(N) (10 for 1000 items). Your code complexity is N (1000 for 1000 items).

Is it possible to declare a variable within a Java while conditional?

In Java it is possible to declare a variable in the initialization part of a for-loop:
for ( int i=0; i < 10; i++) {
// do something (with i)
}
But with the while statement this seems not to be possible.
Quite often I see code like this, when the conditional for the while loop needs to be updated after every iteration:
List<Object> processables = retrieveProcessableItems(..); // initial fetch
while (processables.size() > 0) {
// process items
processables = retrieveProcessableItems(..); // update
}
Here on stackoverflow I found at least a solution to prevent the duplicate code of fetching the processable items:
List<Object> processables;
while ((processables = retrieveProcessableItems(..)).size() > 0) {
// process items
}
But the variable still has to be declared outside the while-loop.
So, as I want to keep my variable scopes clean, is it possible to declare a variable within the while conditional, or is there some other solution for such cases?
You can write a while loop using a for loop:
while (condition) { ... }
is the same as
for (; condition; ) { ... }
since all three bits in the brackets of the basic for statement declaration are optional:
BasicForStatement:
for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement
Similarly, you can just rewrite your while loop as a for loop:
for (List<Object> processables;
(processables = retrieveProcessableItems(..)).size() > 0;) {
// ... Process items.
}
Note that some static analysis tools (e.g. eclipse 4.5) might demand that an initial value is assigned to processables, e.g. List<Object> processables = null. This is incorrect, according to JLS; my version of javac does not complain if the variable is left initially unassigned.
No it's not possible.
It doesn't really make too much sense either: unlike a for loop where you can set up the initial state of the "looping variable", in a while loop you test the value of an existing variable, akin to the conditional check of the for loop.
Of course, if you're concerned about variables "leaking" into other parts of your code, you could enclose the whole thing in an extra scope block:
{
/*declare variable here*/
while(...){...}
}
Alternatively, convert the while loop into a for loop.
Make a do/while:
String value;
do {
value = getValue();
...your processing
} while (value != null && !value.isEmpty());

Terminate Iterable.forEach early [duplicate]

This question already has answers here:
Limit a stream by a predicate
(19 answers)
Closed 8 years ago.
I have a set and a method:
private static Set<String> set = ...;
public static String method(){
final String returnVal[] = new String[1];
set.forEach((String str) -> {
returnVal[0] += str;
//if something: goto mark
});
//mark
return returnVal[0];
}
Can I terminate the forEach inside the lambda (with or without using exceptions)?
Should I use an anonymous class?
I could do this:
set.forEach((String str) -> {
if(someConditions()){
returnVal[0] += str;
}
});
but it wastes time.
implementation using stream.reduce
return set.parallelStream().reduce((output, next) -> {
return someConditions() ? next : output;
}).get(); //should avoid empty set before
I am looking for the fastest solution so exception and a 'real' for each loop are acceptable if they are fast enough.
I'm reluctant to answer this even though I'm not entirely sure what you're attempting to accomplish, but the simple answer is no, you can't terminate a forEach when it's halfway through processing elements.
The official Javadoc states that it is a terminal operation that applies against all elements in the stream.
Performs an action for each element of this stream.
This is a terminal operation.
If you want to gather the results into a single result, you want to use reduction instead.
Be sure to consider what it is a stream is doing. It is acting on all elements contained in it - and if it's filtered along the way, each step in the chain can be said to act on all elements in its stream, even if it's a subset of the original.
In case you were curious as to why simply putting a return wouldn't have any effect, here's the implementation of forEach.
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
The consumer is explicitly passed in, ad this is done independently of the actual iteration going on. I imagine you could throw an exception, but that would be tacky when more elegant solutions likely exist.

what is the difference between executing For loop Java

Could you tell me, what is the difference between For Loop Java in Code A and B? while both of them gives a same result in executing? and i know what they are doing, but why is For loop written this way in the code *A*
Thanks
The code
//Code A
public class MyArray {
public static void main (String[] args){
int[] a ={1,10,30,40,50};
for (int i : a)
{
System.out.println(i);
}
}
}
//====================================
//Code B
public class MyArray{
public static void main (String[] args){
int[] a ={1,10,30,40,50};
for (int i=0;i< a.length; i++)
{
System.out.println(a[i]);
}
}
}
Iterating over a collection is uglier than it needs to be. Consider the following method, which takes a collection of timer tasks and cancels them:
void cancelAll(Collection<TimerTask> c) {
for (Iterator<TimerTask> i = c.iterator(); i.hasNext(); )
i.next().cancel();
}
The iterator is just clutter. Furthermore, it is an opportunity for error. The iterator variable occurs three times in each loop: that is two chances to get it wrong. The for-each construct gets rid of the clutter and the opportunity for error. Here is how the example looks with the for-each construct:
void cancelAll(Collection<TimerTask> c) {
for (TimerTask t : c)
t.cancel();
}
for each is just a better way of iterating.
Limitation:
in for-each loop you will not be able to know which number of element(index of the element in collection) you are processing, you need to define counter for the same, while in simple for loop i tells you the number of the element you are processing.
Code A by is just syntactic sugar for code B and works on Java versions 5 or later.
The advantage is that you do not have to handle the mundane indexing code on your own.
Code A is also known as the foreach loop
Plus Code A also works if instead of int[] you had a Collection, thus giving you a uniform way of iterating over arrays and collections (or to be ever more precise, any subclass of Iterable)
Practically, no difference, but code A is easier to read and harder to make a mistake.
The shorter version of the for loop means for each index in the array, which quite simply is easier to understand.
The other for loop is a most commonly used which starts from a assigned starting value and goes on till the end of array.
The selection depends on the situation according to me. There might be a time when using the codeA format would give a better understanding to the one who debugging the application.
The answers here have not pointed to a certain vital difference: in code A, you cannot simply change the elements of the array, because the i is just a reference, while in code B, you can do a[i] = //something.
If your array was an array of some Objects and you just wanted to use Mutability, then there is no difference.
Actually both codes are equal as first code if in the right-hand side of the for(:) array rather than an Iterable object (as in this case), the internal code uses an int index counter and checks against array.length. which is equivalent to:
for (int i=0;i< a.length; i++)
{
System.out.println(a[i]);
}
Advantage of first code is its internally handle the end condition and short in writing then the second one.
but if object is iterable then it converts to:
for(Iterator<String> i = iteratableObject.iterator(); i.hasNext(); ) {
String item = i.next();
System.out.println(item);
}

How can i counter a ConcurrentModificationException?

if have the following problem:
I have a List which i am going through using the enhanced for loop. Every time i want to remove sth, out of the list, i get a ConcurrentModificationException. I already found out why this exception is thrown, but i don`t know how i can modify my code, so that its working. This is my code:
for(Subject s : SerData.schedule)
{
//Checking of the class is already existing
for(Classes c : s.classes)
{
if(c.day == day &c.which_class == which_class)
{
int index = getclassesindex(s.classes, new Classes(day, which_class));
synchronized (s) {
s.classes.remove(index);
}
}
}
//More code....
}
I also tried out this implementation.
for(Subject s : SerData.schedule)
{
//Checking of the class is already existing
Iterator<Classes> x = s.classes.iterator();
while(x.hasNext())
{
Classes c = x.next();
if(c.day == day &c.which_class == which_class)
{
int index = getclassesindex(s.classes, new Classes(day, which_class));
synchronized (s) {
s.classes.remove(index);
}
}
}
//More code....
}
not working either...
Is there a common used, standard solution? (Hopefully sth. that is not obvious :D )
The main reason this issue occurs is because of the semantic meaning of your for-each loop.
When you use for-each loops, the data structure that is being traversed cannot be modified.
Essentially anything of this form will throw this exception:
for( Object o : objCollection )
{
// ...
if ( satisfiesSomeProperty ( o ) )
objList.remove(o); // This is an error!!
// ...
}
As a side note, you can't add or replace elements in the collection either.
There are a few ways to perform this operation.
One way is to use an iterator and call the remove() method when the object is to be removed.
Iterator <Object> objItr = objCollection.iterator();
while(objItr.hasNext())
{
Object o = objItr.next();
// ...
if ( satifiesSomeProperty ( o ) )
objItr.remove(); // This is okay
// ...
}
This option has the property that removal of the object is done in time proportional to the iterator's remove method.
The next option is to store the objects you want to remove, and then remove them after traversing the list. This may be useful in situations where removal during iteration may produce inconsistent results.
Collection <Object> objsToRemove = // ...
for( Object o : objCollection )
{
// ...
if ( satisfiesSomeProperty ( o ) )
objsToRemove.add (o);
// ...
}
objCollection.removeAll ( objsToRemove );
These two methods work for general Collection types, but for lists, you could use a standard for loop and walk the list from the end of the list to the front, removing what you please.
for (int i = objList.size() - 1; i >= 0; i--)
{
Object o = objList.get(i);
// ...
if ( satisfiesSomeProperty(o) )
objList.remove(i);
// ...
}
Walking in the normal direction and removing could also be done, but you would have to take care of how incrementation occurs; specifically, you don't want to increment i when you remove, since the next element is shifted down to the same index.
for (int i = 0; i < objList.size(); i++)
{
Object o = objList.get(i);
// ...
if ( satisfiesSomeProperty(o) )
{
objList.remove(i);
i--;
}
//caveat: only works if you don't use `i` later here
// ...
}
Hope this provides a good overview of the concepts and helps!
Using Iterator.remove() should prevent the exception from being thrown.
Hm if I get it right you are iterating over a collection of classes and if a given class matches some criteria you are looking for the its index and try to remove it?
Why not just do:
Iterator<Classes> x = s.classes.iterator();
while(x.hasNext()){
Classes c = x.next();
if(c.day == day && c.which_class == which_class) {
x.remove();
}
}
Add synchronization if need be (but I would prefer a concurrent collection if I were you), preferably change the "==" to equals(), add getters/setters etc. Also the convention in java is to name variables and methods using camelCase (and not separating them with "_").
Actually this is one of the cases when you have to use an iterator.
From the javadoc on ConcurrentModificationException:
"if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception."
So within your
for (Classes c : s.classes)
you are executing
s.classes.remove(index)
and the iterator is doing just what its contract says. Declare the index(es) in a scope outside the loop and remove your target after the loop is done.
Iterator<Classes> classesIterator = s.classes.iterator();
while (classesIterator.hasNext()) {
Classes c = classesIterator.next();
if (c.day == day && c.which_class == which_class) {
classesIterator.remove();
}
}
There is no general solution for Collection subclasses in general - most iterators will become invalid if the collection is modified, unless the modification happens through the iterator itself via Iterator.remove().
There is a potential solution when it comes to List implementations: the List interface has index-based add/get/set/remove operations. Rather than use an Iterator instance, you can iterate through the list explicitly with a counter-based loop, much like with arrays. You should take care, however, to update the loop counter appropriately when inserting or deleting elements.
Your for-each iterator is fail-fast and this is why remove operation fails as it would change the collection while traversing it.
What implementation of List interface are you using?
Noticed synchronisation on Subject, are you using this code concurrently?
If concurrency is the case, then I would recommend using CopyOnWriteArrayList. It doesn't need synchronisation and its for-each iterator doesn't throw ConcurrentModificationException.

Categories

Resources