Videos
Why is this interface used?
Because it supports the basic operations that would allow a client programmer to iterate over any kind of collection (note: not necessarily a Collection in the Object sense).
Why are the methods... not directly coded to the data structure implementation itself?
They are, they're just marked Private so you can't reach into them and muck with them. More specifically:
- You can implement or subclass an
Iteratorsuch that it does something the standard ones don't do, without having to alter the actual object it iterates over. - Objects that can be traversed over don't need to have their interfaces cluttered up with traversal methods, in particular any highly specialized methods.
- You can hand out
Iteratorsto however many clients you wish, and each client may traverse in their own time, at their own speed. - Java
Iteratorsfrom the java.util package in particular will throw an exception if the storage that backs them is modified while you still have anIteratorout. This exception lets you know that theIteratormay now be returning invalid objects.
For simple programs, none of this probably seems worthwhile. The kind of complexity that makes them useful will come up on you quickly, though.
You ask: "Why are the methods hasNext(), next() and remove() not directly coded to the data structure implementation itself?".
The Java Collections framework chooses to define the Iterator interface as externalized to the collection itself. Normally, since every Java collection implements the Iterable interface, a Java program will call iterator to create its own iterator so that it can be used in a loop. As others have pointed out, Java 5 allows us to direct usage of the iterator, with a for-each loop.
Externalizing the iterator to its collection allows the client to control how one iterates through a collection. One use case that I can think of where this is useful is when one has an an unbounded collection such as all the web pages on the Internet to index.
In the classic GoF book, the contrast between internal and external iterators is spelled out quite clearly.
A fundamental issue is deciding which party conrols the iteration, the iterator or the client that uses the iterator. When the client controls the iteration, the iterator is called an external iterator, and when the iterator controls it, the iterator is an internal iterator. Clients that use an external iterator must advance the traversal and request the next element explicitly from the iterator. In contrast, the client hands an internal iterator an operation to perform, and the iterator applies that operation to every element ....
External iterators are more flexible than internal iterators. It's easy to compare two collections for equality with an external iterator, for example, but it's practically impossible with internal iterators ... But on the other hand, internal iterators are easier to use, because they define the iteration logic for you.
For an example of how internal iterators work, see Ruby's Enumerable API, which has internal iteration methods such as each. In Ruby, the idea is to pass a block of code (i.e. a closure) to an internal iterator so that a collection can take care of its own iteration.
Is the "itr" not an object??
It's a reference.
Wasn't it impossible to make object of an interface??
You can not instantiate an interface. Here, a parent type (Iterator) reference is referencing an object of child type.
and what is that special thing
myPrecious.iterator();??
Here iterator is a function in the class whose object is myPrecious. Check the definition of the function, iterator here for an example.
wasn't it
new Iterator();to instantiate an object??
You can instantiate a non-abstract class using the keyword, new. You can instantiate an anonymous class by using new on the interface name as shown here for an example.
The point of an interface is:
- You cannot directly create an instance of the interface, an object, you are correct.
- A class may implement the interface. It declares that it implements the interface and it contains all the methods that the interface contains (unless it’s an abstract class, but then again you can’t create objects from it, so let’s forget this situation for now).
- You may assign a reference to an instance (object) to a variable (or parameter) that is declared to have the interface type.
So to answer your questions:
Iterator itr = myPrecious.iterator();Is the "itr" not an object?? …
myPrecious.iterator() returns a real object, and a reference to the object is stored into itr. The object probably belongs to some class that we haven’t heard of and do not need to care about. All that we know is that that class implements the Iterator interface. This means that we can use the iterator as specified by that interface.
wasn't it
new Iterator();to instantiate an object??
Good question. Answer: In the end it is. However, very often in real-world programming we are calling an ordinary method in order to get a new object. That method must in turn use new. Or call another method that uses new (etc.). And this is where things go nicely hand in hand: since we don’t know the actual class of the object, we cannot use new ourselves. But myPrecious, your collection object, does know the class to use for instantiating an iterator object, so it can use new for us. And return the created iterator object to us.
One way to check is through this little code experiment:
List<String> myList = new ArrayList<>();
Iterator itr = myList.iterator();
System.out.println(itr.getClass());
On my Java 11 it prints:
class java.util.ArrayList$Itr
Output on other java versions may be different. You notice that the output doesn’t mention the Iterator interface as the class of the iterator object, but instead some ArrayList$Itr. This means a class named Itr declared inside the ArrayList class. So yes, the iterator is really an object belonging to a class.