Creating custom Iterator Java? - java

I'm a bit confused about how to implement a custom iterator for a class in Java. I'm required to essentially make an ArrayList without using the inbuilt libraries already available to me. I understand the basics of creating the class but I'm having trouble understanding how to get the Iterator to fit into all of this. I have the following:
I have created a generic class that implements the iterable interface as such it looks something like this:
public class MyArrayList<T> implements Iterable<T> {
I've then got to create a class called MyIterator which according to the wording of the document is a stand alone class. This seems fairly straight forward I make a new class called MyIterator and have it implement the iterator interface so it looks something like this:
public class MyIterator<T> implements Iterator<T>{
My confusion lies in the following. The document says that the Iterator needs to be in it's own class, but how then do I access the data members in "MyArrayList" to fully implement hasNext() and next() for example. As the data members in the underlying array are private (as they should be) I don't see how an external class can fully implement these methods. Am I misunderstanding what is required? By separate class is it still a part of the "MyArrayList" class but defined differently?
I hope that helps, as I said I think I understand what is required of me I just am not exactly sure where my Iterator fits into all of this.

While the iterator has to be a separate class *, that class will probably have some relation to your Iterable class.
It's often a nested/inner class, precisely because it needs to access the values of the class (and that's what pretty much what inner classes are made for).
Granted, if the Iterable is a List you could implement an Iterator without any "internal" access at all, but you usually still want to get access to the internals for things like checking the modCount (to throw a ConcurrentModificationException when the Iterable is structurally modified while you iterate over it ... and to prevent that exception if you modify it via the Iterator itself).
* you could implement it with your Iterable instance itself, but that would break the contract as soon as the user uses two iterators at the same time.

You have to declare your own methods hasNext(), next(), remove(). It has to know how to iterate over your own class, how to go to next element and how to check whether next element exists.

Related

what is need that ArrayList and Vector implements List directly as AbstractList class has already implemented the List interface?

As we know if super class implements an interface ,
then sub-class also implicity implements that interface.
Well, it does mean that you can tell that ArrayList and Vector implement the List API without looking at the source / documentation for AbstractList.
In other words, it makes the code / documentation marginally easier to understand.
However, that is only a possible explanation. For the real (complete) explanation you would need to ask the designers.

Relationship between class and iterator interface

Will a class become an iterator object itself if it implements an iterator interface.
For example,
public class StringGridIterator implements Iterator<String>{
//some methods here...
}
or Do I need to specifically create a variable reference to an iterator object that will iterate through a certain String objects?
like this...
Iterator<String> it = object.iterator();
I don't know if this is clear enough for you to understand since I am still struggling with understanding Java concept like class and object myself.. Just leave a comment if you don't understand what I am trying to say.
A class will not become an Iterator object by implementation. You may be thinking of extending a class. (See: What's the difference between the implements & extends keywords in Java).
From your examples, it looks like you are attempting to do 2 different things: class inheritance vs. an iterator object. The .iterator() method returns an Iterator containing the elements of your object.

Why are iterators private?

Iterators are nested classes exported to clients. Then why are the declared private instead of public ?
eg:
private abstract class HashIterator<E> implements Iterator<E> {
private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
public Map.Entry<K,V> next() {
return nextEntry();
}
}
It hides implementation details which class users dont need to know. Eg HashSet
public Iterator<E> iterator()
Returns an iterator over the elements in this set.
it does not say which concrete Iterator is returned, it is a private class invisible for users, users dont need to know implementation details and HashSet designers are free to change the implementation without notice
In the general case, they don't have to be private; i.e. if you are designing a data structure, there is nothing stopping you from declaring your iterator class as public.
However, private iterators are "good design" if the data structure is intended to be a string abstraction; i.e. one where the internal representation is hidden from client code.
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. Or at least, not without relaxing the abstraction boundary of the data structure.
Another way to look at this is that making the iterator class public would not achieve anything. The caller typically doesn't need to use anything apart from the methods in the Iterator API. And if it does, then the solution is to extend the iterator API (interface) to provide the additional methods.
There are many reasons and caveats to it:
Keeping class private would not allow client to depend on the actual implementation
Keeps the code loosely coupled
It strictly applies code to an interface as it will not allow you to cast to actual implementation because of it being private
It logically emphasizes that the class is only useful to the parent class and no other code should depend on that
Actual implementation can change anytime without notice from Java team as already stated in other answer.

How does Iterator ties into Collection Interface

I am new to Java.
Java has Collection interface
public interface Collection<E> extends Iterable<E>
{ // a lot of other stuff.
Iterator<E> iterator(); }
What I don't understand is how does Iterator Interface is tying into Collection Interface ? When I look at the Collection Interface, I see that it has a method that returns Iterator. When Iterator for Collection is created, where does JVM looks to create an object that IS-An Iterator ?
Thanks !
The JVM doesn't do it; the code that ultimately implements the abstract iterator() method just creates an instance of an appropriate class and returns it. For example, in the class ArrayList(), which implements List which extends Collection, there is a method that implements iterator() by returning an instance of a class that understand how ArrayList is implemented internally. This Iterator class is private to the java.util package -- normally you'll never see its name.
Ok so this is all pretty advanced java stuff and it will be pretty tough to explain in one go here but I will do my best.
BACKGROUND: If you don't know about those funny <E> things, you should do a bit of looking into Java Generics. Also, if you don't already, you really need to know what an interface is. One really basic way to think of it is as a promised bit of functionality a class promises to provide.
Now to answer your question: There are three interfaces in the above code snippet, and if you want to create your own collection class you will need to provide implementations of all three:
The first is Collection. This is a simple concept that maps to the real world, it is literally a "collection" of objects. I think you get this...
The next one is Iterable this defines a singe type of behavior that all collections need to provide: the ability to traverse all of the elements of a collection, while accessing them one by one ie "iterate" over them. But it doesn't stop there. As you pointed out the Iterable functionality is provided by objects that implement the last interface:
Iterator: objects that implement this interface, actually know how to traverse the elements of a collection class, they hide all the details of how its actually done from thier clients and proved a few clean easy methods for actually doing it like hasNext() which checks to see if there are more things in the collection to visit and next() which actually visits the next thing.
phew...
The code for the iterator() method determines which concrete implementation of Iterator to return.
All non-abstract classes that implement the Collection interface are required to provide an implementation for the iterator() method.

Why do many Collection classes in Java extend the abstract class and implement the interface as well?

Why do many Collection classes in Java extend the Abstract class and also implement the interface (which is also implemented by the given abstract class)?
For example, class HashSet extends AbstractSet and also implements Set, but AbstractSet already implements Set.
It's a way to remember that this class really implements that interface.
It won't have any bad effect and it can help to understand the code without going through the complete hierarchy of the given class.
From the perspective of the type system the classes wouldn't be any different if they didn't implement the interface again, since the abstract base classes already implement them.
That much is true.
The reason they do implement it anyways is (probably) mostly documentation: a HashSet is-a Set. And that is made explicit by adding implements Set to the end, although it's not strictly necessary.
Note that the difference is actually observable using reflection, but I'd be hard-pressed to produce some code that would break if HashSet didn't implement Set directly.
This may not matter much in practice, but I wanted to clarify that explicitly implementing an interface is not exactly the same as implementing it by inheritance. The difference is present in compiled class files and visible via reflection. E.g.,
for (Class<?> c : ArrayList.class.getInterfaces())
System.out.println(c);
The output shows only the interfaces explicitly implemented by ArrayList, in the order they were written in the source, which [on my Java version] is:
interface java.util.List
interface java.util.RandomAccess
interface java.lang.Cloneable
interface java.io.Serializable
The output does not include interfaces implemented by superclasses, or interfaces that are superinterfaces of those which are included. In particular, Iterable and Collection are missing from the above, even though ArrayList implements them implicitly. To find them you have to recursively iterate the class hierarchy.
It would be unfortunate if some code out there uses reflection and depends on interfaces being explicitly implemented, but it is possible, so the maintainers of the collections library may be reluctant to change it now, even if they wanted to. (There is an observation termed Hyrum's Law: "With a sufficient number of users of an API, it does not matter what you promise in the contract; all observable behaviors of your system will be depended on by somebody".)
Fortunately this difference does not affect the type system. The expressions new ArrayList<>() instanceof Iterable and Iterable.class.isAssignableFrom(ArrayList.class) still evaluate to true.
Unlike Colin Hebert, I don't buy that people who were writing that cared about readability. (Everyone who thinks standard Java libraries were written by impeccable gods, should take look it their sources. First time I did this I was horrified by code formatting and numerous copy-pasted blocks.)
My bet is it was late, they were tired and didn't care either way.
From the "Effective Java" by Joshua Bloch:
You can combine the advantages of interfaces and abstract classes by adding an abstract skeletal implementation class to go with an interface.
The interface defines the type, perhaps providing some default methods, while the skeletal class implements the remaining non-primitive interface methods atop the primitive interface methods. Extending a skeletal implementation takes most of the work out of implementing an interface. This is the Template Method pattern.
By convention, skeletal implementation classes are called AbstractInterface where Interface is the name of the interface they implement. For example:
AbstractCollection
AbstractSet
AbstractList
AbstractMap
I also believe it is for clarity. The Java Collections framework has quite a hierarchy of interfaces that defines the different types of collection. It starts with the Collection interface then extended by three main subinterfaces Set, List and Queue. There is also SortedSet extending Set and BlockingQueue extending Queue.
Now, concrete classes implementing them is more understandable if they explicitly state which interface in the heirarchy it is implementing even though it may look redundant at times. As you mentioned, a class like HashSet implements Set but a class like TreeSet though it also extends AbstractSet implements SortedSet instead which is more specific than just Set. HashSet may look redundant but TreeSet is not because it requires to implement SortedSet. Still, both classes are concrete implementations and would be more understandable if both follow certain convention in their declaration.
There are even classes that implement more than one collection type like LinkedList which implements both List and Queue. However, there is one class at least that is a bit 'unconventional', the PriorityQueue. It extends AbstractQueue but doesn't explicitly implement Queue. Don't ask me why. :)
(reference is from Java 5 API)
Too late for answer?
I am taking a guess to validate my answer. Assume following code
HashMap extends AbstractMap (does not implement Map)
AbstractMap implements Map
Now Imagine some random guy came, Changed implements Map to some java.util.Map1 with exactly same set of methods as Map
In this situation there won't be any compilation error and jdk gets compiled (off course test will fail and catch this).
Now any client using HashMap as Map m= new HashMap() will start failing. This is much downstream.
Since both AbstractMap, Map etc comes from same product, hence this argument appears childish (which in all probability is. or may be not.), but think of a project where base class comes from a different jar/third party library etc. Then third party/different team can change their base implementation.
By implementing the "interface" in the Child class, as well, developer's try to make the class self sufficient, API breakage proof.
In my view,when a class implements an interface it has to implement all methods present in it(as by default they are public and abstract methods in an interface).
If we don't want to implement all methods of interface,it must be an abstract class.
So here if some methods are already implemented in some abstract class implementing particular interface and we have to extend functionality for other methods that have been unimplemented,we will need to implement original interface in our class again to get those remaining set of methods.It help in maintaining the contractual rules laid down by an interface.
It will result in rework if were to implement only interface and again overriding all methods with method definitions in our class.
I suppose there might be a different way to handle members of the set, the interface, even when supplying the default operation implementation does not serve as a one-size-fits-all. A circular Queue vs. LIFO Queue might both implement the same interface, but their specific operations will be implemented differently, right?
If you only had an abstract class you couldn't make a class of your own which inherits from another class too.

Categories