Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why java Iterator interface should be implemented as inner class?

I recently read a book "The Java Tutorials" 3rd edition. It talks about inner class implementation as the picture shows.

In the 3rd paragraph, it says "The Stack class itself should not implement the Iterator interface, because...".

I cannot find any reason that Stack class should not implement Iterator. The reason given is NOT persvasive.

Could you explain it?

Inner classInner class

like image 584
Zachery Avatar asked Apr 18 '13 16:04

Zachery


People also ask

Why iterator interface is used in Java?

Java Iterator Interface of java collections allows us to access elements of the collection and is used to iterate over the elements in the collection(Map, List or Set). It helps to easily retrieve the elements of a collection and perform operations on each element.

Should iterator be private?

One reason is that making the iterator class private prevents undesirable coupling; i.e. it stops some external class from depending on the actual iterator code in a way that would make future code changes harder. Another reason is that in most cases an extensible public iterator class couldn't be instantiated anyway.

How iterator works internally in Java?

The iterator for most simple java collections just keeps a pointer of where in the collection the iterator is currently at. Calling . next() will advance the iterator. It doesn't copy the elements, and just returns the next element from the collection.

What is the benefit of adding an iterator to the list class?

By using Iterator, we can perform both read and remove operations. Iterator must be used whenever we want to enumerate elements in all Collection framework implemented interfaces like Set, List, Queue, Deque and also in all implemented classes of Map interface.


4 Answers

Fundamentally, an iterator is stateful - it needs to know where it's pointing within the collection. That doesn't belong as part of the collection itself - and the explanation given is the right one... it's entirely possible to have two independent iterator objects, iterating over the same collection object. How would you model that if the collection itself implemented the Iterator interface? It's possible (e.g. creating a new instance of the collection which in turn held a reference to the original collection), but it would be really ugly.

There are separate concerns here:

  • The collection of data
  • A cursor positioned within the collection

Separate concerns => separate classes.

The simplest way of persuading yourself of this is probably to try to implement your own collection though - and then have multiple iterators. For example, you might want to try:

List<String> foo = new MyListImplementation<String>();
foo.add("a");
foo.add("b");

// The enhanced for loop uses Iterable/Iterator for non-arrays
for (String x : foo) {
    for (String y : foo) {
        System.out.println(x + " " + y);
    }
}

That should print out:

a a
a b
b a
b b

Try implementing it without having two classes, and see how you do, bearing separation of concerns in mind.

like image 190
Jon Skeet Avatar answered Sep 28 '22 09:09

Jon Skeet


The stack should not implement Iterator itself because then you could have only one iterator at a time, and iterating over a stack would change the stack.

For the latter issue, notice that the nested class has a "currentItem" field. This field would need to be in "Stack", and would change when next() is called. Iterating over a collection should not change the collection.

The first problem is more serious: suppose two people iterate over the stack (or one method wishes to create two iterators over the stack). Then if iterator() returned this, the two iterators would be the same thing. Calling next() on one would move the other. Chaos.

like image 21
John Tang Boyland Avatar answered Sep 28 '22 08:09

John Tang Boyland


A Stack cannot be its own Iterator because a Stack supports more than one Iterator.

You might want to iterate over the Stack more than once. These iterations might occur at different times, or even the same time. Multiple iterations at the same time clearly require multiple objects. Multiple iterations at different times require multiple objects because the Iterator interface does not support returning to the start.

like image 30
Andy Thomas Avatar answered Sep 28 '22 08:09

Andy Thomas


There are 2 reasons I can think of off the top of my head.

Multiple types of iterators

You may want multiple types of iterators that iterate in different ways. For instance, both a Forward Iterator and a Backward Iterator (iterates from end of the container to beginning).

Multiple instances of iterators

If you have a multiple pass algorithm and/or nested loops, each loop may want its own iterator that keeps track of where it is in the container independent of the other iterators.


It would be difficult if not impossible to support these functionalities with the Iterator interface implemented in the Stack class.

like image 42
Nicu Stiurca Avatar answered Sep 28 '22 10:09

Nicu Stiurca