This question already has answers here:
Does Java's foreach loop preserve order?
(2 answers)
Closed 7 years ago.
Does a java for-each loop guarantee that the elements will be presented in order if invoked on a list? In my tests it does seem to, but I can't seem to find this explicitly mentioned in any documentation
List<Integer> myList;// [1,2,3,4]
for (Integer i : myList) {
System.out.println(i.intValue());
}
#output
1,2,3,4
Yes. The foreach loop will iterate through the list in the order provided by the iterator() method. See the documentation for the Iterable interface.
If you look at the Javadoc for List you can see that a list is an "ordered collection" and that the iterator() method returns an iterator that iterates "in proper sequence".
The foreach loop will use the iterator built into the Collection, so the order you get results in will depend whether or not the Collection maintains some kind of order to the elements.
So, if you're looping over an ArrayList, you'll get items in the order they were inserted (assuming you didn't go on to sort the ArrayList). If you're looping over a HashSet, all bets are off, since HashSets don't maintain any ordering.
If you need to guarantee an order to the elements in the Collection, define a Comparator that establishes that order and use Collections.sort(Collection<T>, Comparator<? super T>).
Yes, the Java language specs ensure that
for (Iterator<Whatever> i = c.iterator(); i.hasNext(); )
whatEver(i.next());
is equivalent to
for (Whatever x : c)
whatEver(x);
no "change in ordering" is allowed.
You could use a for loop, a la for (int i = 0; i < myList.length(); i++) if you want to do it in an ordered manner. Though, as far as I know, foreach should do it in order.
Related
I was asked in an interview what is the advantage of using iterator over for loop or what is the advantage of using for loop over iterator?
Can any body please answer this?
First of all, there are 2 kinds of for loops, which behave very differently. One uses indices:
for (int i = 0; i < list.size(); i++) {
Thing t = list.get(i);
...
}
This kind of loop isn't always possible. For example, Lists have indices, but Sets don't, because they're unordered collections.
The other one, the foreach loop uses an Iterator behind the scenes:
for (Thing thing : list) {
...
}
This works with every kind of Iterable collection (or array)
And finally, you can use an Iterator, which also works with any Iterable:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
...
}
So you in fact have 3 loops to compare.
You can compare them in different terms: performance, readability, error-proneness, capability.
An Iterator can do things that a foreach loop can't. For example, you can remove elements while you're iterating, if the iterator supports it:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
if (shouldBeDeleted(thing) {
it.remove();
}
}
Lists also offer iterators that can iterate in both directions. A foreach loop only iterates from the beginning to an end.
But an Iterator is more dangerous and less readable. When a foreach loop is all you need, it's the most readable solution. With an iterator, you could do the following, which would be a bug:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
System.out.println(it.next().getFoo());
System.out.println(it.next().getBar());
}
A foreach loop doesn't allow for such a bug to happen.
Using indices to access elements is slightly more efficient with collections backed by an array. But if you change your mind and use a LinkedList instead of an ArrayList, suddenly the performance will be awful, because each time you access list.get(i), the linked list will have to loop though all its elements until the ith one. An Iterator (and thus the foreach loop) doesn't have this problem. It always uses the best possible way to iterate through elements of the given collection, because the collection itself has its own Iterator implementation.
My general rule of thumb is: use the foreach loop, unless you really need capabilities of an Iterator. I would only use for loop with indices with arrays, when I need access to the index inside the loop.
Iterator Advantage:
Ability to remove elements from Collections.
Ability to move forward and backward using next() and previous().
Ability to check if there more elements or not by using hasNext().
Loop was designed only to iterate over a Collection, so if you want just to iterate over a Collection, its better to use loop such as for-Each, but if you want more that that you could use Iterator.
The main difference between Iterator and the classic for loop, apart from the obvious one of having or not having access to the index of the item you're iterating, is that using Iterator abstracts the client code from the underlying collection implementation, allow me to elaborate.
When your code uses an iterator, either in this form
for(Item element : myCollection) { ... }
this form
Iterator<Item> iterator = myCollection.iterator();
while(iterator.hasNext()) {
Item element = iterator.next();
...
}
or this form
for(Iterator iterator = myCollection.iterator(); iterator.hasNext(); ) {
Item element = iterator.next();
...
}
What your code is saying is "I don't care about the type of collection and its implementation, I just care that I can iterate through its elements". Which is usually the better approach, since it makes your code more decoupled.
On the other hand, if you're using the classic for loop, as in
for(int i = 0; i < myCollection.size(); i++) {
Item element = myCollection.get(i);
...
}
Your code is saying, I need to know the type of collection, because I need to iterate through its elements in a specific way, I'm also possibly going to check for nulls or compute some result based on the order of iteration. Which makes your code more fragile, because if at any point the type of collection you receive changes, it will impact the way your code works.
Summing it up, the difference is not so much about speed, or memory usage, is more about decoupling your code so that is more flexible to cope with change.
if you access to data by number (e.g. "i"), it is fast when you use array. because it goes to element directly
But, other data structure (e.g. tree, list), it needs more time, because it start from first element to target element. when you use list. It needs time O(n). so, it is to be slow.
if you use iterator, compiler knows that where you are. so It needs O(1)
(because, it start from current position)
finally, if you use only array or data structure that support direct access(e.g. arraylist at java). "a[i]" is good. but, when you use other data structure, iterator is more efficient
Unlike other answers, I want to point another things;
if you need to perform the iteration in more than one place in your code, you will likely end up duplicating the logic. This clearly isn’t a very extensible approach. Instead, what’s needed is a way to separate the logic for selecting the data from the code that actually processes it.
An iterator solves these problems by providing a generic interface for looping over a set of data so that the underlying data structure or storage mechanism — such as an array- is hidden.
Iterator is a concept not an implementation.
An iterator provides a number of operations for traversing and accessing data.
An iterator may wrap any datastructure like array.
One of the more interesting and useful advantages of using iterators is the capability to wrap or decorate another iterator to filter the return values
An iterator may be thread safe while a for loop alone cannot be as it is accessing elements directly. The only popular thread-safety iterator is CopyOnWriteArrayList but it is well known and used often so worth mentioning.
This is from the book that it is https://www.amazon.com/Beginning-Algorithms-Simon-Harris/dp/0764596748
I stumbled on this question. The answer lies to the problems Iterator tries to solve:
access and traverse the elements of an aggregate object without exposing its representation
define traversal operations for an aggregate object without changing its interface
This question already has answers here:
Calling remove in foreach loop in Java [duplicate]
(11 answers)
Closed 9 years ago.
I was wondering why I cannot remove elements from a list, when I'm iterating it with a foreach-loop like:
List<Object> objects = new ArrayList<Object>();
Object one = new Object();
Object two = new Object();
Object three = new Object();
objects.add(one);
objects.add(two);
objects.add(three);
and then removing the elements like:
foreach(Object o : objects){
objects.remove(three); //I know that o is my current object
}
It seems like the foreach-loop doesn't allow to remove objects, which are "still" in the loop-queue. Am I correct?
And why does the for-int-loop doesn't care about this? In this loop I can easily remove objects, which are still in the loop.
Thanks
Well, initially the question was tagged C#, now removed. however....
It's not true that a for/loop doesn't care if you remove an element from the collection.
If you remove elements while going forward, you will have problem indexing elements after the one you have removed because the index doesn't match anymore your next element.
You avoid problems with for/loop only if you loop in reverse order (from the last element to the first)
The foreach suffers internally of the same problem. The enumerator maintains a Current position to the element, if you remove the element and then advance to the Next position, the Current indexer doesn't point to the element after the one removed, but to an element two position after the one removed.
For example:
Suppose a string collection of "birds", "animals", and "fishes"
At the foreach start, the internal Current is 0 ( points to "birds")
you remove "birds", so "animals" is at index 0 (where Current still points to)
You advance to the Next element (Current=1, points to "fishes")
Without the exception the Next advance will exit the loop.
foreach has not been designed to allow this scenario.
As far as Java is concerned, the answer is in the javadoc (emphasis mine):
The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
For Java at least, you are correct: the problem is the iterator used to go through the elements in the list does not allow modification. It will throw a ConcurrentModificationException. To quote the Java API javadoc for java.util.ArrayList
The iterators returned by this class's iterator and listIterator
methods are fail-fast: if the list is structurally modified at any
time after the iterator is created, in any way except through the
iterator's own remove or add methods, the iterator will throw a
ConcurrentModificationException. Thus, in the face of concurrent
modification, the iterator fails quickly and cleanly, rather than
risking arbitrary, non-deterministic behavior at an undetermined time
in the future.
The alternative is to use an iterator that allows such modifications, rather than the default for ArrayList or to create the iterator explicitly, rather than use the foreach loop, and use the methods it has to alter the contents whilst iterating through the list.
See Calling remove in foreach loop in Java, in general use Iterator and check with hasNext if there are more elements
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
What are the Advantages of Enhanced for loop and Iterator in Java ?
Is there a performance difference between a for loop and a for-each loop?
Below code shows that with both for loop as well as with iterator we can iterate the elements of collection then what is the difference between for loop and iterator and why we should use only iterator in case of collection
ArrayList<String> list=new ArrayList<String>();
list.add("dipu");
list.add("alok");
list.add("alok");
list.add("jyoti");
ArrayList<Integer> al=new ArrayList<Integer>();
al.add(1);
al.add(2);
String a[]={"a","b"};
for(int i=0;i<list.size();i++)
{
System.out.println(list.get(i));;
}
for(Integer t:al)
{
System.out.println(t);
}
for (Iterator iter = list.iterator(); iter.hasNext();)
{
System.out.println(iter.next());
}
Iterator it=list.iterator();
while(it.hasNext())
{
String st=it.next().toString();
System.out.println(st);
}
Though I'm not familiar with the Java Iterator, it seems very similar to .NET's IEnumerable.
The advantages of the enumerator/iterator are:
You don't have to know the size of the collection, which in some cases can require N steps to determine, increasing execution time (though it remains technically linear). Instead, you just keep moving to the next element until there aren't any.
Because the cardinality of the collection doesn't have to be known, iterators can allow collections to be generated dynamically, or "streamed" with elements being added while you begin work on what you already have. For instance, you could derive from Iterator and/or overload iterator getters to create classes that generate finite or infinite series "lazily", figuring out what each element in your enumerable collection is when you ask for it instead of when you define the collection. You could also set up a buffered stream, where you process records, packets, etc that you have received, while another thread or process works ahead of you to queue up more for you to work on.
Any collection that can provide an iterator can be traversed in exactly the same way, instead of having to know whether it's indexable, what the method or member is that defines size, etc etc etc. Iterator implementations thus provide an adapter to allow the same code to work on any collection passed to it.
Does Java have an equivalent to .NET extension methods (static methods that are not part of the class definition, but that work on instances of the type and can be called as if they were instance methods)? If so, you can define methods that take an Iterator and produce a result, which could be another Iterator. .NET's Linq library is based heavily on these, providing a very powerful collection-manipulation framework allowing for common operations to be chained together, each operating on the result of the previous operation.
Iterators are just generally safer I would say, no risk of accessing an index that isn't there. They also have a little more flexibility since you can go backwards and forwards with them whereas for loops only go one way and in many languages you cannot alter the value of the loop index within the loop (i.e. you cannot change the increment rate).
They are also the ONLY way to remove items from a collection while iterating through them. Removing an item from a collection while you were in a for loop through it would be disastrous and is generally not even allowed by Java, I forget what the exception is, but I've got one for doing that before.
Think about it, once you remove the item all the other ones shift down. Meanwhile on your next iteration your index was still incremented meaning 2 things.
First is that you will skip whatever the next element is as it was shifted to the position you just deleted from.
Second is that your loop will extend beyond the size of the collection which you have now altered.
I try to explain it with two short sentences:
With the enhanced for loop its easier to loop over it (more human readable..)
With the iterators it is possible to modify the list during the iteration, which is with the other methods not possible
The 'stream' you're iterating on might not even be indexable. That is, the iterator makes possible a very convenient 'lazy-evaluation' pattern where data isn't even loaded/constructed until the iterator asks for it. This is wonderful for repositories and database access, as well as networking.
I'm using LinkedHashSet. I want to insert items at the 0th position, like:
Set<String> set = new LinkedHashSet<String>();
for (int i = 0; i < n; i++) {
set.add(0, "blah" + i);
}
I'm not sure how linked hash set is implemented, is inserting going to physically move all addresses of current items, or is it the same cost as inserting as in a linked-list implementation?
Thank you
------ Edit ---------------
Complete mess up by me, was referencing ArrayList docs. The Set interface has no add(index, object) method. Is there a way to iterate over the set backwards then? Right now to iterate I'm doing:
for (String it : set) {
}
can we do that in reverse?
Thanks
Sets are, by definition, independent of order. Thus, Set doesn't have add(int , Object) method available.
This is also true of LinkedHashSet http://download.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html
LinkedHashSet maintains insertion order and thus all elements are added at the end of the linked list. This is achieved using the LinkedHashMap. You can have a look at the method linkEntry in LinkedHashMap http://www.docjar.com/html/api/java/util/LinkedHashMap.java.html
Edit: in response to edited question
There is no API method available to do this. But you can do the following
Add Set to a List using new ArrayList(Set)
Use Collections.reverse(List)
Iterate this list
Judging by the source code of LinkedHashMap (which backs LinkedHashSet -- see http://www.docjar.com/html/api/java/util/LinkedHashMap.java.html ), inserts are cheap, like in a linked list.
To answer your latest question, there is no reverse iterator feature available from LinkedHashSet, even though internally the implementation uses a doubly linked list.
There is an open Request For Enhancement about this:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4848853
Mark Peters links to functionality available in guava, though their reverse list actually generates a reverse list.
As already mentioned, LinkedHashSet is build on LinkedHashMap, which is built on HashMap :) Javadocs says that it takes constant time to add an element into HashMap, assuming that your hash function is implemented properly. If your hash function is not implemented well, it may take up to O(n).
Iteration backwards in not supported at this moment.
You can't add elements to the front of a LinkedHashSet... it has no method such as add(int, Object) nor any other methods that make use of the concept of an "index" in the set (that's a List concept). It only provides consistent iteration order, based on the order in which elements were inserted. The most recently inserted element that was not already in the set will be the last element when you iterate over it.
And the Javadoc for LinkedHashSet explicitly states:
Like HashSet, it provides constant-time performance for the basic operations (add, contains and remove), assuming the hash function disperses elements properly among the buckets.
Edit: There is not any way to iterate over a LinkedHashSet in reverse short of something like copying it to a List and iterating over that in reverse. Using Guava you could do that like:
for (String s : Lists.reverse(ImmutableList.copyOf(set))) { ... }
Note that while creating the ImmutableList does require iterating over each element of the original set, the reverse method simply provides a reverse view and doesn't iterate at all itself.
My question, is, whether the sequence of elements picked from a list will always be the same,
is this construction behaviour is deterministic for
java "List"s - descendants of java.util.List
2) question, if I use for(Object o: list) construction and inside the loop's body increment a variable,
will it be the index of list's elements? So, how it goes through list's elements, from 0 to size()-1 or chaotically?
List.get(i)
will always return this element?
3) question ( I suppose for the 2-nd question the answer will be negative, so:)
for (int i=0; i < list.size(); i++) {
}
is the best way if I need to save the index of an element and later get it back from a list by its id?
Overall:
I simply need to save a position in the list in every object's field.
object.setPosInList(currentIndexOfTheLoop)
Now clear?
Any descendant of List will provide an Iterator that iterates through the list in a deterministic proper order.
The for-each loop construct is compiled into code that uses the iterator() method which for a List is described in the following way in the api:
iterator
public Iterator iterator()
Returns an iterator over the elements in this list in proper sequence.
Specified by:iterator in interface Collection
Returns:an iterator over the elements in this list in proper sequence.
1) Yes
2) Yes
3) No.
Also note that on LinkedLists using get(i) is O(i) while getting the next element from an iterator (which is what for-each does) is O(1).
whether the sequence of elements picked from a list will always be the same
Yes. Quote from the API Javadoc:
An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list.
2:
how it goes through list's elements, from 0 to size()-1
Yes.
3: No, you generally don't need to iterate through the list manually to get to an indexed element. The most used List implementation is ArrayList, which is random access, i.e. you can access any of its elements directly, in constant time. For LinkedList, list.get(i) does iterate through the list till the desired element implicitly, as this implementation is not random-access.
According to the API doc contract of List.iterator():
Returns an iterator over the elements
in this list in proper sequence.
So yes, iteration over the elements of a List should happen from index 0 to size()-1. Theoretically, you could encounter an implementation that violates the contract, but then that's a bug in the implementation, not in your code.
Also, look at java.util.ListIterator.
List<Object> list = new ArrayList<Object>();
for(ListIterator<Object> it = list.listIterator(); it.hasNext(); )
{
Object o = it.next();
it.nextIndex();
it.prevIndex(); // etc
}
for(Object o : list) makes implicit use of the List's Iterator, returning elements in a deterministic order. for(int i = 0; i < list.size(); i++) also selects items from the List in a deterministic order, as by definition, Lists are ordered.
#MichaelBorgwardt Such an implementation would be broken - it doesn't satisfy the contract for List.iterator.