How does iterable work? - java

Hey guys I've been teaching myself java and I working on this assignment.
http://ljing.org/games/focus/
So I write a Linked list from scratch, I write a Deque class using the LinkedList class
But!
There's only one question I don't understand about the classes Iterator.
I just don't understand what does the Class Deque Iterator is supposed to do.
Also, I have this in my code:
class Deque<Item> implements Iterable<Item>.
But then the compiler complains that in my Deque class I need to override a method
#Override
public Iterator<Item> iterator()
{
throw new UnsupportedOperationException("Not supported yet.");
}
But I don't understand why

There are two different interfaces in Java for iteration that are important, Iterable and Iterator. They each serve a different purpose.
Iterable
When something implements this interface, this means that it can be iterated on. This is useful for us because Java gives us a shortcut for iterating over things that implement Iterable using a for-each loop:
List<String> elements = ... ; // List is an instance of Iterable
for (String element : elements)
System.out.println(element);
Anything that is an instance of Iterable can be used in a for-each loop. If you have your own custom MyDeque class that implements Iterable, then you can use that in a for-each as well:
MyDeque<String> elements = ... ;
for (String element : elements)
System.out.println(element);
This brings us to...
Iterator
This interface is how the iteration is actually performed. The for-each loop compiles to something like this:
MyDeque<String> elements = ... ;
for (Iterator<String> $iter = elements.iterator(); $iter.hasNext();) {
String element = $iter.next();
System.out.println(element);
}
This piece of code is functionally equivalent to the for-each above. hasNext() is the continuation condition (do I have more stuff to give you?) and next() actually gives you the next element, or throws a NoSuchElementException if we don't have anything else.
The point of making your custom deque implement Iterable is just to make it so you can iterate over the elements in your deque using something like a for loop. Its Iterator implementation is the thing that will let you actually do that iteration.

An iterator is a concept for accessing the elements in a collection. Because you say implements Iterable<Item>, you tell the compiler that you provide this mechanism of accessing the elements of your Deque. But that's not enough yet. Besides claiming you will do it, you actually have to do it. In this case, doing it is implementing the method.
What happens if you don't:
Because you told the compiler you would provide this, you have to implement the method iterator(), which is part of this access concept. If you do not implement the method, the compiler complains and tells you "hey, you said you would do it. So keep your word!".
There are two ways to solve this:
1.) In the first place, don't give your word you would provide the access concept through an iterator - remove implements Iterable<Item>
2.) Keep your word and implement the method. You will have to write an own Iterator class for this. That's a rather short task once you know what to do.

Related

Enhanced for-loop does not accept Iterator

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);
}

Contains method for Iterable and Iterator?

Is there a simple method to check if an element is contained in an iterable or iterator, analogous to the Collection.contains(Object o) method?
I.e. instead of having to write:
Iterable<String> data = getData();
for (final String name : data) {
if (name.equals(myName)) {
return true;
}
}
I would like to write:
Iterable<String> data = getData();
if (Collections.contains(data, myName)) {
return true;
}
I'm really surprised there is no such thing.
In Java 8, you can turn the Iterable into a Stream and use anyMatch on it:
String myName = ... ;
Iterable<String> data = getData();
return StreamSupport.stream(data.spliterator(), false)
.anyMatch(name -> myName.equals(name));
or using a method reference,
return StreamSupport.stream(data.spliterator(), false)
.anyMatch(myName::equals);
Guava has the functions Iterables.contains and Iterators.contains which do what you want. You can look at the source to see how to implement them yourself.
An iterator is a sort of cursor which can be moved over the elements of any collection of elements. So its inner state is mainly the pointer to the current element. If you would try to find out whether it "contains" a certain element you would have to move the cursor and therefore modify the inner state. Modifying the state by simply asking a question is surely a bad thing to do.
That is even the problem with the mentioned Guava. It will modify the iterator object by simply calling the contains method.
An iterable on the other hand is simply an interface telling the compiler that there is something to iterate over. In most cases the iterable object will be the collection itself. If you would add methods like "contains" to the interface Iterable you would get a (simplified) version of the Collection interface - which already exists. So there is no need for that.
If you are stuck in your code at some place where you have a reference to an iterable but need functionality of a collection you should think about refactoring your code. Either you should use the interface collection consistently or ask yourself why you should better not call collection methods at this point. So your problem is most probably a result of a suboptimal code design.
On the other hand I would consider it to be a strange thing to use Iterable as type for parameters or variables anyway. Technically you can do this but I think it is meant to be used in loops only.
From the JavaDoc for Iterable:
Implementing this interface allows an object to be the target of the "foreach" statement
I'm sorry to say what you're trying to do is impossible.
.contains is a method of the interface Collection and not Iterable so maybe you can use that interface.
An Iterator is like a pointer/reference to an element in a collection. It is not the collection itself. So, you can't use iterator.contains(). Also, an Iterable interface is used to iterate over a collection using a for-each loop. A collection and Iterator / Iterable are different.

Converting Linked List to a Circular Linked List in JAVA

Is there any way to convert an object of LinkedList class to a circular linked list.
Or is there any predefined class like CircularLinkedList in java.util
Some thing like this (some thing like http://docs.oracle.com/javase/1.4.2/docs/api/java/util/LinkedList.html)
Any help would be really appreciated....
Thanks in Advance :-)
No, the LinkedList is encapsulated in a way which makes it impossible to connect its tail to its head. I don't think that any of the default collections supports that, because then it wouldn't fulfill the contract for Iterable anymore, which says that an iterator got to get to the end sometime.
When you need a data structure like that, you have to implement it yourself.
Have a look at Guava's Iterables.cycle method.
public static <T> Iterable<T> cycle(Iterable<T> iterable)
Returns an iterable whose iterators cycle indefinitely over the elements of iterable.
That iterator supports remove() if iterable.iterator() does. After remove() is called, subsequent cycles omit the removed element, which is no longer in iterable. The iterator's hasNext() method returns true until iterable is empty.
Refer doc : http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Iterables.html#cycle%28java.lang.Iterable%29 .

Need of Iterator class in Java?

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

How to get the Collection of an iterator in Java?

Often there is the need to setup an ArrayList<>. One of the constructors takes a collection, but there is no constructor that takes an iterator.
What if I have an iterator? Is there a way to "reach up" to the collection that offers the iterator in order to use the ArrayList<> constructor?
Specifically I have the iterator offered by PropertiesConfiguration.getKeys() which is part of org.apache.commons.
There's no such thing, an Iterator's Collection. An Iterator can be created independently of a Collection. It can be obtained from any Iterable, or you can even create a class implementing an iterator.
However, you can obtain an ArrayList from an Iterator by iterating it and adding its elements one by one:
Iterator<X> it = ...;
List<X> list = new ArrayList<X>();
while (it.hasNext()) {
list.add(it.next());
}
Note, however, that this cannot be done reliably for every possible iterator, since there's the possibility that an iterator will iterate forever, thus causing an infinite loop and most probably an OutOfMemoryError.
I'd suggest you take a look at Google Guava, an utility library from Google. It has a class called Lists, which allows you to do the following:
Iterator<X> it = ...;
List<X> list = Lists.newArrayList(it);
The library has tons of methods extremely useful for everyday Java coding. It contains mostly everything you want but cannot find in the standard Java 6 API.
There is no truly general way to do this, because in Java, Iterator is just an interface with three methods: next, hasNext and remove.
When you obtain an iterator, you use a factory method that gives you an instance of some class implementing the interface. If you know the specific class, you can look at its documentation or source to find if there is a way to find the collection it is iterating over.
But there are many such classes. In the case of ArrayList, look in the source code to see what kind of iterator you are getting.
EDIT:
Here is the source code for ArrayList in Open JDK 7: http://www.docjar.com/html/api/java/util/ArrayList.java.html
The iterator over an ArrayList is an instance of the private inner class Itr. This should not be too surprising. The iterator comes from a factory method, after all, so you're really not supposed to know what kind of iterator you are getting. In fact, if you were able to get the class of this instance and access its methods (say, via reflection) you would be doing a bad thing. This iterator is part of the (internal) implementation of the ArrayList class and (as #merryprankster points out) can change in the future.
I don't know if its possible, but in my opinion, a such function should not exist because an iterator may not come from a collection. For example, one could create an iterator which chains over multiple collections !

Categories

Resources