Excuse me if this has been asked before. My search did not bring up any other similar question. This is something that surprised me in Java.
Apparently, the enhanced for-loop only accepts an array or an instance of java.lang.Iterable. It does not accept a java.util.Iterator as a valid obj reference to iterate over. For example, Eclipse shows an error message for the following code. It says: "Can only iterate over an array or an instance of java.lang.Iterable"
Set<String> mySet = new HashSet<String>();
mySet.add("dummy");
mySet.add("test");
Iterator<String> strings = mySet.iterator();
for (String str : strings) {
// Process str value ...
}
Why would this be so? I want to know why the enhanced for-loop was designed to work this way. Although an Iterator is not a collection, it can be used to return one element at a time from a collection. Note that the only method in the java.lang.Iterable interface is Iterator<T> iterator() which returns an Iterator. Here, I am directly handing it an Iterator. I know that hasNext() and next() can be used but using the enhanced for-loop makes it look cleaner.
One thing I understand now is that I could use the enhanced for-loop directly over mySet. So I don't even need the extra call to get an Iterator. So, that would be the way to code this, and yes - it does make some sense.
The enhanced for loop was part of JSR 201. From that page, you can download the proposed final draft documents, which include a FAQ section directly addressing your question:
Appendix I. Design FAQ
Why can't I use the enhanced for statement with an Iterator (rather
than an Iterable or array)?
Two reasons: (1) The construct would not
provide much in the way on syntactic improvement if you had an
explicit iterator in your code, and (2) Execution of the loop would
have the "side effect" of advancing (and typically exhausting) the
iterator. In other words, the enhanced for statement provides a
simple, elegant, solution for the common case of iterating over a
collection or array, and does not attempt to address more complicated
cases, which are better addressed with the traditional for statement.
Why can't I use the enhanced for statement to:
remove elements as I traverse a collection ("filtering")?
simultaneously iterate over multiple collections or arrays?
modify the current slot in an array or list?
See Item 1 above. The expert group considered these cases, but
opted for a simple, clean extension that dose(sic) one thing well. The
design obeys the "80-20 rule" (it handles 80% of the cases with 20% of
the effort). If a case falls into the other 20%, you can always use an
explicit iterator or index as you've done in the past.
In other words, the committee chose to limit the scope of the proposal, and some features that one could imagine being part of the proposal didn't make the cut.
The enhanced for loop was introduced in Java 5 as a simpler way to
iterate through all the elements of a Collection [or an array].
http://www.cis.upenn.edu/~matuszek/General/JavaSyntax/enhanced-for-loops.html
An iterator is not a collection of elements,
it is an object that enables a programmer to traverse a container.
An iterator may be thought of as a type of pointer.
https://en.wikipedia.org/wiki/Iterator
So enhanced for loops work by going through all the elements in a structure that contains elements, while an iterator doesn't contain elements, it acts more like a pointer.
In your example, you are creating an iterator but not using it properly. As to answer your question of why the exception is being thrown- it's from the line:
for (String str : strings) {
"strings" is an iterator here, not a collection that you can iterate through. So you have a few options you can iterate through the set by using an enhanced for loop:
for(String myString : mySet){
//do work
}
or you can iterate through the set using an iterator:
Iterator<String> strings = mySet.iterator();
while(strings.hasNext()){
//do work
}
hope you find this helpful.
The error comes because you are trying to iterate over an Iterator, and not a List or Collection. If you want to use the Iterator, i recommend you to use it next() and hasNext() methods:
Set<String> mySet = new HashSet<String>();
mySet.add("dummy");
mySet.add("test");
Iterator<String> strings = mySet.iterator();
while(strings.hasNext()){
String temp = strings.next();
System.out.println(temp);
}
Related
I know there are a lot of similar questions here on SO. But it seems this wasn't discussed before.
In general I want to know, why an Iterator should be used over a For-Each loop, if no element will be removed? So, basically just iterating over a Collection, and the only used modifier is add.
I'm aware that Iterator is the only save option if an element is removed from a Collection.
Performance is no argument, because the For-Each will be transformed into an Iterator by the compiler.
The Iterator is more verbose, so +1 to For-Each.
Is there any reliable point to use an Iterator over For-Each in the described scenario?
You need to use an Iterator loop instead of a foreach loop if
you need to be able to remove items during processing, OR
you need to process the last item differently than the others.
Also, an Iterator may be more natural if you want to be able to skip an element based on characteristics of its previous element.
Additionally, for Lists, a ListIterator loop may sometimes be more convenient than a foreach loop, as it can provide the indexes of the previous and next elements, and (even apart from the indexes) allows you to recognize the first element of the iteration. Furthermore, you need a ListIterator if
you have to replace elements in the underlying List, OR
you ever need to back up.
The question might be pretty vague I know. But the reason I ask this is because the class must have been made with some thought in mind.
This question came into my mind while browsing through a few questions here on SO.
Consider the following code:
class A
{
private int myVar;
A(int varAsArg)
{
myVar = varAsArg;
}
public static void main(String args[])
{
List<A> myList = new LinkedList<A>();
myList.add(new A(1));
myList.add(new A(2));
myList.add(new A(3));
//I can iterate manually like this:
for(A obj : myList)
System.out.println(obj.myVar);
//Or I can use an Iterator as well:
for(Iterator<A> i = myList.iterator(); i.hasNext();)
{
A obj = i.next();
System.out.println(obj.myVar);
}
}
}
So as you can see from the above code, I have a substitute for iterating using a for loop, whereas, I could do the same using the Iterator class' hasNext() and next() method. Similarly there can be an example for the remove() method. And the experienced users had commented on the other answers to use the Iterator class instead of using the for loop to iterate through the List. Why?
What confuses me even more is that the Iterator class has only three methods. And the functionality of those can be achieved with writing a little different code as well.
Some people might argue that the functionality of many classes can be achieved by writing one's own code instead of using the class made for the purpose. Yes,true. But as I said, Iterator class has only three methods. So why go through the hassle of creating an extra class when the same job can be done with a simple block of code which is not way too complicated to understand either.
EDIT:
While I'm at it, since many of the answers say that I can't achieve the remove functionality without using Iterator,I would just like to know if the following is wrong, or will it have some undesirable result.
for(A obj : myList)
{
if(obj.myVar == 1)
myList.remove(obj);
}
Doesn't the above code snippet do the same thing as remove() ?
Iterator came long before the for statement that you show in the evolution of Java. So that's why it's there. Also if you want to remove something, using Iterator.remove() is the only way you can do it (you can't use the for statement for that).
First of all, the for-each construct actually uses the Iterator interface under the covers. It does not, however, expose the underlying Iterator instance to user code, so you can't call methods on it.
This means that there are some things that require explicit use of the Iterator interface, and cannot be achieved by using a for-each loop.
Removing the current element is one such use case.
For other ideas, see the ListIterator interface. It is a bidirectional iterator that supports inserting elements and changing the element under the cursor. None of this can be done with a for-each loop.
for(A obj : myList)
{
if(obj.myVar == 1)
myList.remove(obj);
}
Doesn't the above code snippet do the same thing as remove() ?
No, it does not. All standard containers that I know of will throw ConcurrentModificationException when you try to do this. Even if it were allowed to work, it is ambiguous (what if obj appears in the list twice?) and inefficient (for linked lists, it would require linear instead of constant time).
The foreach construct (for (X x: list)) actually uses Iterator as its implementation internally. You can feed it any Iterable as a source of elements.
And, as others already remarked: Iterator is longer in Java than foreach, and it provides remove().
Also: how else would you implement your own provider class (myList in your example)? You make it Iterable and implement a method that creates an Iterator.
For one thing, Iterator was created way before the foreach loop (shown in your code sample above) was introduced into Java. (The former came in Java2, the latter only in Java5).
Since Java5, indeed the foreach loop is the preferred idiom for the most common scenario (when you are iterating through a single Iterable at a time, in the default order, and do not need to remove or index elements). Note though that the foreach uses an iterator in the background for standard collection classes; in other words it is just syntactic sugar.
Iterator, listIterator both are used to allow different permission to user, like list iterator have 9 methods but iterator have only 3 methods, but have remove functionality which you can't achieve with for loop. Enumeration is another thing which is also used to give only read permissions.
Iterator is an implementation of the classical GoF design pattern. In that way you can achieve clear behaviour separation from the 'technical code' which iterates (the Iterator) and your business code.
Imagine you have to change the 'next' behaviour (say, by getting not the next element but the next EVEN element). If you rely only on for loops you will have to change manually every single for loop, in a way like this
for (int i; i < list.size(); i = i+2)
while if you use an Iterator you can simply override/rewrite the "next()" and "hasNext()" methods and the change will be visible everywhere in your application.
I think answer to your question is abstraction. Iterator is written because to abstract iterating over different set of collections.
Every collection has different methods to iterate over their elements. ArrayList has indexed access. Queues has poll and peek methods. Stack has pop and peek.
Usually you only need to iterate over elements so Iterator comes into play. You do not care about which type of Collection you need to iterate. You only call iterator() method and user Iterator object itself to do this.
If you ask why not put same methods on Collection interface and get rid of extra object creation. You need to know your current position in collection so you can not implement next method in Collection because you can not use it on different locations because every time you call next() method it will increment index (simplifying every collection has different implementation) so you will skip some objects if you use same collection at different places. Also if collection support concurrency than you can not write a multi-thread safe next() method in collection.
It is usually not safe to remove an object from collection iterating by other means than iterator. Iterator.remove() method is safest way to do it. For ArrayList example:
for(int i=0;i
I have one list:
List<Object> myList = new ArrayList<Object>();
To get from this list there are two methods:
1.
for(Object obj : myList )
{
// some code
}
2.
Iterator<Object> objIt = myList.iterator();
while(obj.hasNext()) {
Object obj = (Object)objIt.next();
// some code
}
My question is which one is memory efficient and iterates fast?
They do the same thing - the enhanced for loop is just syntactic sugar for the longhand version (for iterables; for arrays it's slightly different). Unless you need the iterator explicitly (e.g. to call remove()) I'd use the first version.
See section 14.14.2 of the Java Language Specification for more details of the exact transformation performed by the compiler.
Using an Iterator provides much safer access to the List from outside the defining class as you cannot accidentally override the entire List for example. You can only ever access one element at a time: the top one.
So the guideline we use is to only use the for each approach inside the defining class and whenever the List needs to be accessed from the outside an iterator has to be used. This also enforces the concept of keeping the logic of how to modify a member inside the class that contains it. All complex operations that are needed outside have to be implemented in public methods inside that class.
Iterator : It gives you the result when needed and don't gets all the result in-memory
The first one is what you call an "enhanced for loop" which was introduced in JDK 1.5+
It is more convenient way of iterating through a list. Also, you do not need to do explicit castings if you are using that.
From the performance perspective, I don't think there isn't much difference between the two.
Enhanced for loop used iterator only inside it. So both are same.
First one is more clear, but if you want to remove elements while visiting the list your only choice is an iterator.
I have a for loop, and I am not sure how it works. I am familiar with:
for(int i = 0; i <= 9; i++)
{
/* implementation */
}
I am confused about a for loop in the following form:
String[] myString = new String[] {"one", "two", "three", "some other stuff"};
String str1 = "", str2 = "";
for (String s : myString)
{
/* implementation */
}
How do these types of for loops work? what do they do differently then regular for loops?
The first is the original for loop. You initialize a variable, set a terminating condition, and provide a state incrementing/decrementing counter (There are exceptions, but this is the classic)
For that,
for (int i=0;i<myString.length;i++) {
System.out.println(myString[i]);
}
is correct.
For Java 5 an alternative was proposed. Any thing that implements iterable can be supported. This is particularly nice in Collections. For example you can iterate the list like this
List<String> list = ....load up with stuff
for (String string : list) {
System.out.println(string);
}
instead of
for (int i=0; i<list.size();i++) {
System.out.println(list.get(i));
}
So it's just an alternative notation really. Any item that implements Iterable (i.e. can return an iterator) can be written that way.
What's happening behind the scenes is somethig like this: (more efficient, but I'm writing it explicitly)
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String string=it.next();
System.out.println(string);
}
In the end it's just syntactic sugar, but rather convenient.
There is an excellent summary of this feature in the article The For-Each Loop. It shows by example how using the for-each style can produce clearer code that is easier to read and write.
Using the first for-loop you manually enumerate through the array by increasing an index to the length of the array, then getting the value at the current index manually.
The latter syntax is added in Java 5 and enumerates an array by using an Iterator instance under the hoods. You then have only access to the object (not the index) and you won't be able to adjust the array while enumerating.
It's convenient when you just want to perform some actions on all objects in an array.
The for-each loop was introduced in Java 1.5 and is used with collections (and to be pedantic, arrays, and anything implementing the Iterable<E> interface ... which the article notes):
http://download.oracle.com/javase/1,5.0/docs/guide/language/foreach.html
Something none of the other answers touch on is that your first loop is indexing though the list. Whereas the for-each loop is using an Iterator. Some lists like LinkedList will iterate faster with an Iterator versus get(i). This is because because link list's iterator keeps track of the current pointer. Whereas each get in your for i=0 to 9 has to recompute the offset into the linked list. In general, its better to use for-each or an Iterator because it will be using Collections iterator, which in theory is optimized for the collection type.
The new for-each loop is just a short hand for the older loop. The new loop is easier to use for arrays and some iterators, but not as flexible, so the old loop has to be using in some situations, like counting from 0 to 9.
The second for loop is any easy way to iterate over the contents of an array, without having to manually specify the number of items in the array(manual enumeration). It is much more convenient than the first when dealing with arrays.
The For-each loop, as it is called, is a type of for loop that is used with collections to guarantee that all items in a collection are iterated over. For example
for ( Object o : objects ) {
System.out.println(o.toString());
}
Will call the toString() method on each object in the collection "objects". One nice thing about this is that you cannot get an out of bounds exception.
Though for-each loop has many advantages but the problem is ,it doesn't work when you want to Filter(Filtering means removing element from List) a List,Can you please any replacement as even traversing through Index is not a good option..
What do you mean by "filtering"? Removing certain elements from a list? If so, you can use an iterator:
for(Iterator<MyElement> it = list.iterator(); it.hasNext(); ) {
MyElement element = it.next();
if (some condition) {
it.remove();
}
}
Update (based on comments):
Consider the following example to illustrate how iterator works. Let's say we have a list that contains 'A's and 'B's:
A A B B A
We want to remove all those pesky Bs. So, using the above loop, the code will work as follows:
hasNext()? Yes. next(). element points to 1st A.
hasNext()? Yes. next(). element points to 2nd A.
hasNext()? Yes. next(). element points to 1st B. remove(). iterator counter does NOT change, it still points to a place where B was (technically that's not entirely correct but logically that's how it works). If you were to call remove() again now, you'd get an exception (because list element is no longer there).
hasNext()? Yes. next(). element points to 2nd B. The rest is the same as #3
hasNext()? Yes. next(). element points to 3rd A.
hasNext()? No, we're done. List now has 3 elements.
Update #2: remove() operation is indeed optional on iterator - but only because it is optional on an underlying collection. The bottom line here is - if your collection supports it (and all collections in Java Collection Framework do), so will the iterator. If your collection doesn't support it, you're out of luck anyway.
ChssPly76's answer is the right approach here - but I'm intrigued as to your thinking behind "traversing through index is not a good option". In many cases - the common case in particular being that of an ArrayList - it's extremely efficient. (In fact, in the arraylist case, I believe that repeated calls to get(i++) are marginally faster than using an Iterator, though nowhere near enough to sacrifice readability).
Broadly speaking, if the object in question implements java.util.RandomAccess, then accessing sequential elements via an index should be roughly the same speed as using an Iterator. If it doesn't (e.g. LinkedList would be a good counterexample) then you're right; but don't dismiss the option out of hand.
I have had success using the
filter(java.util.Collection collection, Predicate predicate)
method of CollectionUtils in commons collections.
http://commons.apache.org/collections/api-2.1.1/org/apache/commons/collections/CollectionUtils.html#filter(java.util.Collection,%20org.apache.commons.collections.Predicate)
If you, like me, don't like modifying a collection while iterating through it's elements or if the iterator just doesn't provide an implementation for remove, you can use a temporary collection to just collect the elements you want to delete. Yes, yes, its less efficient compared to modifying the iterator, but to me it's clearer to understand whats happening:
List<Object> data = getListFromSomewhere();
List<Object> filter = new ArrayList<Object>();
// create Filter
for (Object item: data) {
if (throwAway(item)) {
filter.add(item);
}
}
// use Filter
for (Object item:filter) {
data.remove(item);
}
filter.clear();
filter = null;