Java: Object Oriented Design; LinkedList and Stack - java

I am writing a BFS and DFS in Java. What I was hoping to do was create one class like this:
/** Preforms BFS and DFS on ...
*/
public class Search{
private XXX toSearch;
// where XXX is an interface of Stack and LinkedList that has
// remove() and add() methods.
public Search(boolean isBFS){
if(isBFS)
toSearch = new LinkedList();
else
toSearch = new Stack();
}
public void preformSearch(){
while(toSearch.size() > 0){
preformSearchOn(toSearch.remove()); // <----- KEY LINE
}
}
private void preformSearchOn(...){...}
}
This class can perform BFS and DFS depending on how it is initialized. What is XXX? I don't think that it exists.
I thought that the entire point of object oriented programing is being able to do cool stuff like this.
What is the cleanest way to handle this?

I think you're looking for the Strategy pattern. The way to do this is not Java specific, or other "cool stuff" for this matter. These types of things transcend languages.
To be more concrete, develop two more classes named BfsStrategy and DfsStrategy. Require that each class implement a certain Strategy interface. Use the class you posted to perform operations on them transparently. (Change class/interface names to be more suitable if you need to.)
For example:
public final class Seeker<E, K> {
private final E structure;
private final SearchStrategy strategy;
public Seeker(final E aStructure, final SearchStrategy aStrategy) {
structure = aStructure;
strategy = aStrategy;
}
public boolean search(K aKey) {
return strategy.search(structure, key); //Pretty generic.
}
}

As far as breadth-first and depth-first searches go, one way to unify both would be to write java.util.Iterator implementations for each one. Let that be your unifying abstraction; it's already part of the JDK.

The common interface is java.util.Queue.
As a first-in-first-out queue you can use (for instance) java.util.LinkedList or java.util.ArrayDeque.
As last-in-first-out queue, you can wrap any Deque using java.util.Collections.asLifoQueue.
Stack, together with is superclass Vector, is deprecated, because it synchronizes all method access, which is often unnecessary. I suspect that's why it doesn't implement Queue.

XXX should be of type java.util.AbstractList as both LinkedList and Stack are derived from it.
But that will not solve you're problem, as the remove() method for each class will behave the same way. In order to get different behaviour you will actual need to call the different removale methods: remove() or pop(). And as method these remove() and pop() are both implemented on java.util.Linkedlist (see Queue interface) there is no need to use the java.util.Stack class either.
You could do call the different methods pop() and remove() with in an if statement, but that would be definitly be an OO anti pateern. An basic OO solution would be to implement 3 classes:
Abstract parent named Search Class
BfsSearch: works with remove() in it's search.
DfsSearch: works with pop() in it's search.
This way, the user of this class can work with Search without needing to know if he is using BfsSearch or DfsSearch.
An even more advanced and flexible OO approach would be to use the Strategy pattern as described by mike. But for simple solutions that don't need this kind of flexibility it might be overkill.
BTW an excelent book on OO design that will explain all these kind of choices and patterns is Larman:
Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition)

Related

Are Java's collections interface and class hierarchy ill done?

I came to know that in Java, LinkedList class implements both Deque and List interfaces.
And this was somewhat confusing to me.
In computer science syllabus, I was never taught that queue can be a list, or more precisely queue can behave like a list. That is, there is stuff that lists can do, but queues can't. But the list can behave like a queue. For example, List interface has the following methods:
add(E e)
add(int index, E element)
But Queue has only the following:
add(E e)
So clearly Queue is not allowed to insert at specific index, which is allowed in List. The same is the case with other operations like Queue.remove() vs. List.remove(int index), List.get(int index) vs. Queue.peek().
In other words, list is a more generalized data structure and can emulate Queue.
Now being capable to emulate is different from having a contract subset. That is, Queue disallows certain operations (indexing) of Listand allows certain operations done only in a particular manner (insert only at the tail and remove only from the head). So Queue does not really do "addition" to the contracts of List. That is precisely why Queue does not extend List in Java collections framework, but both extend Collection interface. I believe that is also why it's incorrect for any class to implement both, as Queue's contract conflicts with the contract of List (which is why they fork out from Collection interface separately). However, LinkedList implements both the interfaces.
I also came across this answer:
The LinkedList implementation happens to satisfy the Deque contract, so why not make it implement the interface?
I still don't get how we can say "LinkedList implementation happens to satisfy the Deque contract". The concept of a queue does not allow insertion at an arbitrary index. Hence, the Queue interface does not have such methods.
However we can only enforce contracts through interfaces and cannot disallow implementation of certain methods. Being list (having "List" in its name), I feel it's not correct to have queue methods peek(), pop() and add(int index, E element) in LinkedList.
I believe, instead we should have separate class LinkedQueue which can have linked implementation for queue, similar to LinkedBlockingQueue which contains linked implementation of BlockingQueue.
Also note that LinkedList is the only class which inherits from both families of lists and queues, that is, there is no other class which implements both List and Queue (AFAIK). Can this be indication that LinkedList is ill done?
Am I plain wrong and thinking unnecessarily?
You're entirely missing the point of programming to interface.
If you need a Queue, you never write:
LinkedList<String> queue = new LinkedList<>();
Because, you're right, that would allow you to use non-queue methods. Instead, you program to the interface like this:
Queue<String> queue = new LinkedList<>();
Now you only have access to the 6 Queue methods (and all the Collection methods). So, even though LinkedList implements more methods, you no longer have access to them.
So, if you need a Queue, you choose the implementation of the Queue interface that best suits the performance, storage, and access characteristics you need, e.g.
LinkedList uses more memory, but it shrinks when queue is emptied.
ArrayDeque uses less memory, but it doesn't shrink.
PriorityQueue is a non-FIFO queue with element priority.
ConcurrentLinkedQueue, ConcurrentLinkedDeque supports multi-threaded concurrent access.
and more...
I was never taught that queue can be a list, or more precisely queue can behave like a list.
Remember that implements defines a behaves like relationship. A LinkedList behaves like a List. A LinkedList behaves like a Deque. A LinkedList behaves like a Queue.
But just because LinkedList behaves like all of those, doesn't mean that List behaves like a Queue or that Queue behaves like a List. They do not.
The behaves like relation only goes one way.
#Andreas's answer is excellent, so mine targets your arguments about what you were or were not taught:
In computer science syllabus, I was never taught that queue can be a list or more precisely queue can behave like a list
A queue is not just any list, but a special kind of list, with its own special properties and constraints.
That is, there is stuff that lists can do, but queues can't.
No, List can do nothing. It provides possibilities to be implemented by a class and if that class decides to implement them then that class can do all that stuff.
But the list can behave like a queue.
No, List does not behave; it only suggests behaviors and classes that implement it can accept all or a subset of them or they can define new ones.
LinkedList is a class that implements both List and Deque interfaces. Each one of these interfaces defines a contract with operations, and in these contracts it is specified what these operations must do. However, it is not specified how these operations are supposed to work.
LinkedList is a class that implements both List and Deque interfaces. So, despite the suffix List is part of the name of the LinkedList class, LinkedList is actually both a List and a Deque, because it implements all of the operations that are defined in the List and Deque interfaces.
So LinkedList is a a List, and it also is a Deque. This doesn't mean that a List should be a Deque, or that a Deque should be a List.
For example, look at the following interfaces:
public interface BloodDrinker {
void drinkBlood();
}
public interface FlyingInsect {
void flyAround();
}
Each one of the interfaces above has a single operation and defines a contract. The drinkBlood operation defines what a BloodDrinker must do, but not how. Same applies for a FlyingInsect: its flyAround operation defines what it must do, but not how.
Now consider the Mosquito class:
public class Mosquito implements FlyingInsect, BloodDrinker {
public void flyAround() {
// fly by moving wings,
// buzzing and bothering everyone around
}
public void drinkBlood() {
// drink blood by biting other animals:
// suck their blood and inject saliva
}
}
Now, this means that a Mosquito is both a FlyingInsect and a BloodDrinker, but why would a blood drinker necessarily be a flying insect, or a flying insect necessarily be a blood drinker? For example, vampires are blood drinkers, but not flying insects, while butterflies are flying insects, but not blood drinkers.
Now, with regard to your argument about Queue disallowing certain List's operations (indexing), and only allowing addition/removal on its ends in a FIFO fashion... I don't think this rationale is correct, at least in the context of the Java Collections Framework. The contract of Deque doesn't explicitly mention that implementors will never ever be able to add/remove/check elements at any given index. It just says that a Deque is:
A linear collection that supports element insertion and removal at both ends.
And it also says that:
This interface defines methods to access the elements at both ends of the deque.
(Emphasis mine).
A few paragraphs later, it does explicitly say that:
Unlike the List interface, this interface does not provide support for indexed access to elements.
(Emphasis mine again).
The key part here is does not provide support. It never forbids implementors to access elements via indexes. It's just that indexed access is not supported through the Deque interface.
Think of my example above: why would a BloodDrinker disallow its implementors to drink something other than blood, i.e. water? Or why would a FlyingInsect disallow its implementors to move in a way different than flying, i.e. walking?
Bottom line, an implementation can adhere to as many contracts as it wishes, as long as these contracts don't contradict each other. And as it's worded in Java (a very careful and subtle wording, I must admit), Deque's contract doesn't contradict List's contract, so there can perfectly exist a class that implements both interfaces, and this happens to be LinkedList.
You are starting from a weak premise:
I was never taught that queue can be a list.
Let us go back to the basics. So what are data structures anyway? Here is how CLSR approaches that question1:
...Whereas mathematical sets are unchanging, the sets manipulated by
algorithms can grow, shrink, or otherwise change over time.
Mathematically, data structures are just sets; dynamic sets. In that sense, a queue can be a list. In fact, there is a problem in CLSR (10.2-3) that explicitly asks you to implement a queue by using a linked list.
On the other hand, object-oriented programming is a paradigm that helps programmers solve problems by adhering to a certain philosophy about the problem and the data. Objects, interfaces, and contracts are all part of this philosophy. Using this paradigm helps us implement the abstract concept of dynamic sets. However, it comes with its own baggage, one of them being the very problem asked about here.
So if you are complaining that the data structures in Java standard library do not strictly adhere to the conventions defined for elementary data structures, you are right. In fact, we do not even need to look further than java.util.Stack to see this2. You are also allowed to roll out your own implementation in any way you want and use them instead of standard library collections.
But to argue that Java, or its standard library for that matter, is broken or ill-done - an extraoridnary claim- you need to be very specific about the use case and clearly demonstrate how the alleged flaw in the library prevents you from achieving the design goals.
1 Introduction to Chapter III, p220
2 Sedgewick and Wayne call java.util.Stack a "wide interface"(p 160) because it allows random access to stack elements; something a stack -as defined in elementary data structures- is not supposed to be capable of.
You are entirely correct in this and not missing the point at all. Java simply made a trade-off between correctness and ease. Making it implement both interfaces was the easy thing to do and the one that was the most useful for developers.
What subtyping means
Correct (sound) subtyping requires substitution to work which requires according to the LSP:
Invariants of the supertype must be preserved in a subtype.
When we say in type theory "A LinkedList is a List and a Queue" we are actually saying that a LinkedList is both a list and a queue at the same time and not that a LinkedList can be thought of as either a list or a queue.
There is a violated invariant of a queue type here (that you cannot modify elements in its middle) so it is incorrect subtyping.
The actual argument that should be had is "whether or not a queue requires that elements can't be modified in the middle or only that they can be modified in the ends in FIFO".
One might argue that the invariants of a Queue are only that you can use it in a FIFO matter and not that you must. That is not the common interpertation of a queue.

Java implementing Queue by extending LinkedList

I've been trying to research a way to implement a Queue using a LinkedList. I've mostly found examples showing me how to do it by literally using "implements" in the class. BUT What I'd like to do, however, is to extend the LinkedList class. For example I have written something like this:
public class TestQueue extends LinkedList{
public TestQueue(){
}
public void enqueue(ObjectType c){
add(c);
}
public Object dequeue(){
return (ObjectType ) remove();
}
// more code for peek and size ect....
}
Is this really all I have to do to use a linked-list type queue? How then would I have to set a head(front) and a tail(rear) to use the linked list just like a queue?
Thanks in advance.
From my understanding and looking up the LinkedList class, you should be good to go as the only thing you should need is the Queue class, which LinkedList already includes. I would recommend taking a quick look at these resources however just to make sure your understanding is where you want it to be.
API from Oracle - http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html
Learning about Queues & Staks (Document) - http://introcs.cs.princeton.edu/java/43stack/

Why does Iterable<T> not provide stream() and parallelStream() methods?

I am wondering why the Iterable interface does not provide the stream() and parallelStream() methods. Consider the following class:
public class Hand implements Iterable<Card> {
private final List<Card> list = new ArrayList<>();
private final int capacity;
//...
#Override
public Iterator<Card> iterator() {
return list.iterator();
}
}
It is an implementation of a Hand as you can have cards in your hand while playing a Trading Card Game.
Essentially it wraps a List<Card>, ensures a maximum capacity and offers some other useful features. It is better as implementing it directly as a List<Card>.
Now, for convienience I thought it would be nice to implement Iterable<Card>, such that you can use enhanced for-loops if you want to loop over it. (My Hand class also provides a get(int index) method, hence the Iterable<Card> is justified in my opinion.)
The Iterable interface provides the following (left out javadoc):
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
Now can you obtain a stream with:
Stream<Hand> stream = StreamSupport.stream(hand.spliterator(), false);
So onto the real question:
Why does Iterable<T> not provide a default methods that implement stream() and parallelStream(), I see nothing that would make this impossible or unwanted?
A related question I found is the following though: Why does Stream<T> not implement Iterable<T>?
Which is oddly enough suggesting it to do it somewhat the other way around.
This was not an omission; there was detailed discussion on the EG list in June of 2013.
The definitive discussion of the Expert Group is rooted at this thread.
While it seemed "obvious" (even to the Expert Group, initially) that stream() seemed to make sense on Iterable, the fact that Iterable was so general became a problem, because the obvious signature:
Stream<T> stream()
was not always what you were going to want. Some things that were Iterable<Integer> would rather have their stream method return an IntStream, for example. But putting the stream() method this high up in the hierarchy would make that impossible. So instead, we made it really easy to make a Stream from an Iterable, by providing a spliterator() method. The implementation of stream() in Collection is just:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
Any client can get the stream they want from an Iterable with:
Stream s = StreamSupport.stream(iter.spliterator(), false);
In the end we concluded that adding stream() to Iterable would be a mistake.
I did an investigation in several of the project lambda mailing lists and I think I found a few interesting discussions.
I have not found a satisfactory explanation so far. After reading all this I concluded it was just an omission. But you can see here that it was discussed several times over the years during the design of the API.
Lambda Libs Spec Experts
I found a discussion about this in the Lambda Libs Spec Experts mailing list:
Under Iterable/Iterator.stream() Sam Pullara said:
I was working with Brian on seeing how limit/substream
functionality[1] might be implemented and he suggested conversion to
Iterator was the right way to go about it. I had thought about that
solution but didn't find any obvious way to take an iterator and turn
it into a stream. It turns out it is in there, you just need to first
convert the iterator to a spliterator and then convert the spliterator
to a stream. So this brings me to revisit the whether we should have
these hanging off one of Iterable/Iterator directly or both.
My suggestion is to at least have it on Iterator so you can move
cleanly between the two worlds and it would also be easily
discoverable rather than having to do:
Streams.stream(Spliterators.spliteratorUnknownSize(iterator,
Spliterator.ORDERED))
And then Brian Goetz responded:
I think Sam's point was that there are plenty of library classes that
give you an Iterator but don't let you necessarily write your own
spliterator. So all you can do is call
stream(spliteratorUnknownSize(iterator)). Sam is suggesting that we
define Iterator.stream() to do that for you.
I would like to keep the stream() and spliterator() methods as being
for library writers / advanced users.
And later
"Given that writing a Spliterator is easier than writing an Iterator,
I would prefer to just write a Spliterator instead of an Iterator (Iterator is so 90s :)"
You're missing the point, though. There are zillions of classes out
there that already hand you an Iterator. And many of them are not
spliterator-ready.
Previous Discussions in Lambda Mailing List
This may not be the answer you are looking for but in the Project Lambda mailing list this was briefly discussed. Perhaps this helps to foster a broader discussion on the subject.
In the words of Brian Goetz under Streams from Iterable:
Stepping back...
There are lots of ways to create a Stream. The more information you
have about how to describe the elements, the more functionality and
performance the streams library can give you. In order of least to
most information, they are:
Iterator
Iterator + size
Spliterator
Spliterator that knows its size
Spliterator that knows its size, and further knows that all sub-splits
know their size.
(Some may be surprised to find that we can extract parallelism even
from a dumb iterator in cases where Q (work per element) is
nontrivial.)
If Iterable had a stream() method, it would just wrap an Iterator with
a Spliterator, with no size information. But, most things that are
Iterable do have size information. Which means we're serving up
deficient streams. That's not so good.
One downside of the API practice outlined by Stephen here, of
accepting Iterable instead of Collection, is that you are forcing
things through a "small pipe" and therefore discarding size
information when it might be useful. That's fine if all you're doing
to do is forEach it, but if you want to do more, its better if you
can preserve all the information you want.
The default provided by Iterable would be a crappy one indeed -- it
would discard size even though the vast majority of Iterables do know
that information.
Contradiction?
Although, it looks like the discussion is based on the changes that the Expert Group did to the initial design of Streams which was initially based on iterators.
Even so, it is interesting to notice that in a interface like Collection, the stream method is defined as:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
Which could be the exact the same code being used in the Iterable interface.
So, this is why I said this answer is probably not satisfactory, but still interesting for the discussion.
Evidence of Refactoring
Continuing with the analysis in the mailing list, it looks like the splitIterator method was originally in the Collection interface, and at some point in 2013 they moved it up to Iterable.
Pull splitIterator up from Collection to Iterable.
Conclusion/Theories?
Then chances are that the lack of the method in Iterable is just an omission, since it looks like they should have moved the stream method as well when they moved the splitIterator up from Collection to Iterable.
If there are other reasons those are not evident. Somebody else has other theories?
If you know the size you could use java.util.Collection which provides the stream() method:
public class Hand extends AbstractCollection<Card> {
private final List<Card> list = new ArrayList<>();
private final int capacity;
//...
#Override
public Iterator<Card> iterator() {
return list.iterator();
}
#Override
public int size() {
return list.size();
}
}
And then:
new Hand().stream().map(...)
I faced the same problem and was surprised that my Iterable implementation could be very easily extended to an AbstractCollection implementation by simply adding the size() method (luckily I had the size of the collection :-)
You should also consider to override Spliterator<E> spliterator().

Better ways to add a "filter" method to a list of elements?

I want to implement a filter method to a list of elements in java, so I can get rid of some elements in the list according to my filter. And, most important, I want to design the interface as simple as possible.
Here's my implementation:
I created a class named EasierList, and in the class, I added a method whose signature and implementation is like below:
public IEasierList<T> filter(ISelection<T> filter) {
List<T> result = new ArrayList<T>();
for(T item : mInternalList) {
if(filter.accept(item)) {
result.add(item);
}
}
mInternalList = result;
return new EasierList<T>(this);
}
As for the ISelection interface, it is quite a easy one:
public boolean accept(T obj);
So, you can tell, the users who use this class need to write some code like this to use the filter:
aEasierList.filter(new ISelection<T>() {
#Override
public boolean accept(T obj) {
// some test
return false;
}
});
And I'm wondering if there is a better way to do this, I mean to make the interface even easier to use?
Thanks in advance!
Two points:
First, you don't have to reinvent the wheel, you can use Guava which already supports filtering and transforming of collections and iterables. Sure, those methods are static, but you can use them for standard List, Collection or Iterable interfaces.
Second, since Java doesn't yet support lambda expressions (planned for Java 8), the verbose anonymous classes are the only way how to implement a function object (if you don't want to create a full blown named class). However, you can help yourself a little by not implementing the anonymous class in-place, but by storing it in a static field:
private static final Predicate<String> startsWithS = new Predicate<String>() {
#Override public boolean apply(String string) {
return string.startsWith("S");
}
}
And then using it like this:
Collection<String> strings = ...
Collection<String> filtered = Collections2.filter(strings, startsWithS);
Edit:
One more important thing should be mentioned: These filter and transform methods do not create a new collection independent on the original. What they create is a "view", which is technically a proxy object that points to the original collection and lazily applies the given Predicate or Function on its elements during iteration, querying etc.
This is sometimes convenient, but you have to remember, that in order to obtain a new collection that is independent (not deeply, of course) on the original one, you need to pass it to a constructor (or a factory) of a new collection.
List<String> filteredList =
new ArrayList<>(Collections2.filter(strings, startsWithS));
By the way, this might be a good occasion to use static import for the filter method to reduce the verbosity a little.
I think this is the best you can do in native Java without resorting to an alternate JVM language (Groovy, Scala) that supports closures.
Commons Collections implements essentially the same pattern - check out docs for CollectionUtils.filter and Predicate. The only downside is it doesn't support generics.
http://commons.apache.org/collections/apidocs/org/apache/commons/collections/CollectionUtils.html
So if you're going that route, you may as well use something that's already written and tested.
C# also has a good solution to this pattern via LINQ and extension methods, which makes something analogous to the above filter method appear like it belongs to the Collection itself.

What are the benefits of the Iterator interface in Java?

I just learned about how the Java Collections Framework implements data structures in linked lists. From what I understand, Iterators are a way of traversing through the items in a data structure such as a list. Why is this interface used? Why are the methods hasNext(), next() and remove() not directly coded to the data structure implementation itself?
From the Java website: link text
public interface Iterator<E> An
iterator over a collection. Iterator
takes the place of Enumeration in the
Java collections framework. Iterators
differ from enumerations in two ways:
Iterators allow the caller to remove
elements from the underlying
collection during the iteration with
well-defined semantics. Method names
have been improved. This interface is
a member of the Java Collections
Framework.
I tried googling around and can't seem to find a definite answer. Can someone shed some light on why Sun chose to use them? Is it because of better design? Increased security? Good OO practice?
Any help will be greatly appreciated. Thanks.
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 Iterator such 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 Iterators to however many clients you wish, and each client may traverse in their own time, at their own speed.
Java Iterators from the java.util package in particular will throw an exception if the storage that backs them is modified while you still have an Iterator out. This exception lets you know that the Iterator may 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.
it is important to keep the collection apart from the pointer. the iterator points at a specific place in a collection, and thus is not an integral part of the collection. this way, for an instance, you can use several iterators over the same collection.
the down-side of this seperation is that the iterator is not aware to changes made to the collection it iterates on. so you cannot change the collection's structure and expect the iterator to continue it's work without "complaints".
Using the Iterator interface allows any class that implements its methods to act as iterators. The notion of an interface in Java is to have, in a way, a contractual obligation to provide certain functionalities in a class that implements the interface, to act in a way that is required by the interface. Since the contractual obligations must be met in order to be a valid class, other classes which see the class implements the interface and thus reassured to know that the class will have those certain functionalities.
In this example, rather than implement the methods (hasNext(), next(), remove()) in the LinkedList class itself, the LinkedList class will declare that it implements the Iterator interface, so others know that the LinkedList can be used as an iterator. In turn, the LinkedList class will implement the methods from the Iterator interface (such as hasNext()), so it can function like an iterator.
In other words, implementing an interface is a object-oriented programming notion to let others know that a certain class has what it takes to be what it claims to be.
This notion is enforced by having methods that must be implemented by a class that implements the interface. This makes sure that other classes that want to use the class that implements the Iterator interface that it will indeed have methods that Iterators should have, such as hasNext().
Also, it should be noted that since Java does not have multiple inheritance, the use of interface can be used to emulate that feature. By implementing multiple interfaces, one can have a class that is a subclass to inherit some features, yet also "inherit" the features of another by implementing an interface. One example would be, if I wanted to have a subclass of the LinkedList class called ReversibleLinkedList which could iterate in reverse order, I may create an interface called ReverseIterator and enforce that it provide a previous() method. Since the LinkedList already implements Iterator, the new reversible list would have implemented both the Iterator and ReverseIterator interfaces.
You can read more about interfaces from What is an Interface? from The Java Tutorial from Sun.
Multiple instances of an interator can be used concurrently. Approach them as local cursors for the underlying data.
BTW: favoring interfaces over concrete implementations looses coupling
Look for the iterator design pattern, and here: http://en.wikipedia.org/wiki/Iterator
Because you may be iterating over something that's not a data structure. Let's say I have a networked application that pulls results from a server. I can return an Iterator wrapper around those results and stream them through any standard code that accepts an Iterator object.
Think of it as a key part of a good MVC design. The data has to get from the Model (i.e. data structure) to the View somehow. Using an Iterator as a go-between ensures that the implementation of the Model is never exposed. You could be keeping a LinkedList in memory, pulling information out of a decryption algorithm, or wrapping JDBC calls. It simply doesn't matter to the view, because the view only cares about the Iterator interface.
An interesting paper discussing the pro's and con's of using iterators:
http://www.sei.cmu.edu/pacc/CBSE5/Sridhar-cbse5-final.pdf
I think it is just good OO practice. You can have code that deals with all kinds of iterators, and even gives you the opportunity to create your own data structures or just generic classes that implement the iterator interface. You don't have to worry about what kind of implementation is behind it.
Just M2C, if you weren't aware: you can avoid directly using the iterator interface in situations where the for-each loop will suffice.
Ultimately, because Iterator captures a control abstraction that is applicable to a large number of data structures. If you're up on your category theory fu, you can have your mind blown by this paper: The Essence of the Iterator Pattern.
Well it seems like the first bullet point allows for multi-threaded (or single threaded if you screw up) applications to not need to lock the collection for concurrency violations. In .NET for example you cannot enumerate and modify a collection (or list or any IEnumerable) at the same time without locking or inheriting from IEnumerable and overriding methods (we get exceptions).
Iterator simply adds a common way of going over a collection of items. One of the nice features is the i.remove() in which you can remove elements from the list that you are iterating over. If you just tried to remove items from a list normally it would have weird effects or throw and exception.
The interface is like a contract for all things that implement it. You are basically saying.. anything that implements an iterator is guaranteed to have these methods that behave the same way. You can also use it to pass around iterator types if that is all you care about dealing with in your code. (you might not care what type of list it is.. you just want to pass an Iterator) You could put all these methods independently in the collections but you are not guaranteeing that they behave the same or that they even have the same name and signatures.
Iterators are one of the many design patterns available in java. Design patterns can be thought of as convenient building blocks, styles, usage of your code/structure.
To read more about the Iterator design pattern check out the this website that talks about Iterator as well as many other design patterns. Here is a snippet from the site on Iterator: http://www.patterndepot.com/put/8/Behavioral.html
The Iterator is one of the simplest
and most frequently used of the design
patterns. The Iterator pattern allows
you to move through a list or
collection of data using a standard
interface without having to know the
details of the internal
representations of that data. In
addition you can also define special
iterators that perform some special
processing and return only specified
elements of the data collection.
Iterators can be used against any sort of collection. They allow you to define an algorithm against a collection of items regardless of the underlying implementation. This means you can process a List, Set, String, File, Array, etc.
Ten years from now you can change your List implementation to a better implementation and the algorithm will still run seamlessly against it.
Iterator is useful when you are dealing with Collections in Java.
Use For-Each loop(Java1.5) for iterating over a collection or array or list.
The java.util.Iterator interface is used in the Java Collections Framework to allow modification of the collection while still iterating through it. If you just want to cleanly iterate over an entire collection, use a for-each instead, but a upside of Iterators is the functionality that you get: a optional remove() operation, and even better for the List Iterator interface, which offers add() and set() operations too. Both of these interfaces allow you to iterate over a collection and changing it structurally at the same time. Trying to modify a collection while iterating through it with a for-each would throw a ConcurrentModificationException, usually because the collection is unexpectedly modified!
Take a look at the ArrayList class
It has 2 private classes inside it (inner classes)
called Itr and ListItr
They implement Iterator and the ListIterator interfaces respectively
public class ArrayList..... { //enclosing class
private class Itr implements Iterator<E> {
public E next() {
return ArrayList.this.get(index++); //rough, not exact
}
//we have to use ArrayList.this.get() so the compiler will
//know that we are referring to the methods in the
//enclosing ArrayList class
public void remove() {
ArrayList.this.remove(prevIndex);
}
//checks for...co mod of the list
final void checkForComodification() { //ListItr gets this method as well
if (ArrayList.this.modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
}
private class ListItr extends Itr implements ListIterator<E> {
//methods inherted....
public void add(E e) {
ArrayList.this.add(cursor, e);
}
public void set(E e) {
ArrayList.this.set(cursor, e);
}
}
}
When you call the methods iterator() and listIterator(), they return
a new instance of the private class Itr or ListItr, and since these inner classes are "within" the enclosing ArrayList class, they can freely modify the ArrayList without triggering a ConcurrentModificationException, unless you change the list at the same time (conccurently) through set() add() or remove() methods of the ArrayList class.

Categories