6

The List interface has two methods listIterator() and iterator(). why both of these are needed.

From the docs:

Iterator<E> iterator()

Returns an iterator over the elements in this list in proper sequence.

ListIterator<E> listIterator()

Returns a list iterator over the elements in this list (in proper sequence).

    ListIterator<E> listIterator(int index)

    Returns a list iterator over the elements in this list (in proper sequence), starting at the 
specified position in the list. The specified index indicates the first element that would be 
returned by an initial call to next. An initial call to previous would return the element with the 
specified index minus one.

so basically, ListIterator() has this additional methods to get previous and next elements while Iterator() has only next elements. Is this only for this purpose, there is another ListIterator() interface and listiterator() method in List inteface

brain storm
  • 30,124
  • 69
  • 225
  • 393
  • Because that's the way they designed it. There's quite an extensive discussion in the JDK documentation. You're not going to get any better information than that there. – user207421 Nov 05 '13 at 22:37
  • http://stackoverflow.com/questions/10977992/difference-between-iterator-and-listiterator?rq=1 – Jason C Nov 21 '13 at 07:02

4 Answers4

5

Since Java 5 it is simply possible to override a method with a more specific return type (called covariant return type). But ListIterator has been introduced with Java 1.2. To avoid casts on usage of iterator() there has to be a new method.

The API could not have been changed from Java 5 on because that would have broken all implementations of List which do not declare iterator() returning ListIterator also if most implementations return a ListIterator instance in real.

A similar dilemma is Enumeration and Iterator. Nowadays Iterator would extend Enumeration and simply add the remove() method. Or better Iterator would have replaced Enumeration and a ModifiableIterator with an additional remove() would have been added.

Arne Burmeister
  • 20,046
  • 8
  • 53
  • 94
3

Specifically they are both required because List is a type of Iterable which specifies an Iterator iterator() method.

Now List could have simply overridden the iterator() method in Iterable to declare a return type of ListIterator which is type of Iterator (thus satisfying the contract). Why this was not done is probably a design decision.

EDIT: @ajb pointed out in a comment that covariant return types were added in Java SE 5 after the List interface was created. This explains why List has both methods, as iterator() return type could not be narrowed to ListIterator in Java 1.2.

Dev
  • 11,919
  • 3
  • 40
  • 53
  • 2
    Probably because then clients would have to downcast the result to `(ListIterator)` to use the additional `ListIterator` functionality. – ajb Nov 05 '13 at 21:40
  • @ajb You can write an overriding method in a sub type such that the return type is more specific than the type return declared in the superclass/interface and the compiler will accept it. Meaning that if you were using a `List` as a `List` in the hypothetical case above that `iterator()` was declared to return `ListIterator` you wouldn't have to downcast. – Dev Nov 05 '13 at 21:44
  • 7
    Covariant return types were added in 1.5, I think. `ListIterator` has been around since 1.2. – ajb Nov 05 '13 at 21:48
  • For what it's worth, it looks like the `iterator()` method of `AbstractSequentialList` is just `return listIterator()`. Why `AbstractList` and `ArrayList` don't do it the same way, I don't know. It looks like they could have. – ajb Nov 05 '13 at 21:59
  • 2
    @ajb I was unaware that covariant returns were an added feature. Thank you for pointing that out, as now it makes perfect sense. – Dev Nov 05 '13 at 22:44
  • @ajb sorry, saw your comment on Java versions too late (after the edit of @Dev) – Arne Burmeister Nov 05 '13 at 22:53
1

Java is designed to be very sturdy--alowing a LOT of language implementation changes that don't affect the code running on the java.

For instance, you can generally replace the "Java JRE 6" with "Java JRE 7" and not have a problem with most code--that's an entire language upgrade with new syntax and all. You can also replace the Java JRE with an open source implementation and you will have the same results--stuff will pretty much just work.

So when they design a class, they have to design it for both the implementor and the coder.

If they were to simply have an ArrayList be "Iterable" then for ArrayLists return an Iterator of type ListIterator then another implementor (OpenJDK) would not be required by the interface to return the correct type--not only that but the user would have no idea what type was being returned without looking at the docs (Eclipse ctrl-space would be less helpful if everyone programmed this way).

Java generally tries to be as explicit as physically possible... this is a Very Good Thing because it stops guessing and related errors.

When it's not possible to make the interfaces and types explicit enough they are extremely deliberate with their documentation, but they avoid that if at all possible.

Bill K
  • 62,186
  • 18
  • 105
  • 157
0

It seems Iterator would be for a singly linked list, ListIterator for a doubly linked list.

La-comadreja
  • 5,627
  • 11
  • 36
  • 64
  • if that is the case, it should be just a method in linkedlist class, and not to have a interface on this. I mean it should act on both arraylist and linkedlist, because if my method expects a List, I can pass either arraylist or linkedlist – brain storm Nov 05 '13 at 21:14