Java Collections hasnext() method - java

Set set = new HashSet();
set.add(1);
set.add(2)
Iterator iter = set.iterator(); // Wher hasnext been overrided
while(iter.hasnext()){
System.out.println(iter.next);
}
Iterator is an interface , set.iterator is returning the Iterator reference .
In HashSet(and its extended ,implemented classes) hasnext is nowhere overriden.
My doubt is where hasnext method is overriden(implemented) and how its linked in this context.
Thanks.

HashSet returns an implementation of Iterator, it doesn't implement Iterator itself. If you look at the source code of HashSet, you can see that it is actually backed by a HashMap:
public HashSet() {
map = new HashMap<E,Object>();
}
and when you call the iterator() method it is the iterator of this map that is returned:
public Iterator<E> iterator() {
return map.keySet().iterator();
}
This map in turn stores a KeySet...
private final class KeySet extends AbstractSet<K> {
public Iterator<K> iterator() {
return newKeyIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
return HashMap.this.removeEntryForKey(o) != null;
}
public void clear() {
HashMap.this.clear();
}
}
Which in turn returns a KeyIterator when its iterator() method is invoked:
private final class KeyIterator extends HashIterator<K> {
public K next() {
return nextEntry().getKey();
}
}
and the HashIterator implements Iterator:
private abstract class HashIterator<E> implements Iterator<E>
So ultimately, the implementation of Iterator is a private subclass of HashIterator which is hidden away as an implementation detail hidden from clients. Such is the beauty of using interfaces!

You can see in the source of the HashSet that the iterator() method is implemented this way:
public Iterator<E> iterator() {
return map.keySet().iterator();
}
In the class AbstractHashedSet the iterator for keyset is implemented
/**
* KeySet iterator.
*/
protected static class KeySetIterator extends EntrySetIterator {
protected KeySetIterator(AbstractHashedMap parent) {
super(parent);
}
public Object next() {
return super.nextEntry().getKey();
}
}
So you have indeed an implementation.
I guess you should re-phrase your question if you experience a problem with the hasNext() method in your code.

HashSet implementation uses a HashMap so the iterator of HashSet is the iterator of the keySet of its HashMap... the keySet implementation of iterator is in AbstractMap class as seen here: AbstractMap-keySet

In the line
Iterator iter = set.iterator();
You are calling a method on Set which returns an instance of a class which implements the Iterator interface. It doesn't matter exactly what class is returned, all you need to care about is that it implements Iterator, hence implements the hasNext() method.
It's likely that the actual class is not part of the API and might change with different version of the JVM. The only thing you can be sure of is that it will implement Iterator.

Related

What object is returned by LinkedList.iterator()?

Consider these an object:
Iterator<String> j = LinkedList.iterator();
Looking at java docs, for LinkedList class there is no implementation of iterator method in LinkedList class, however, the implementation is in AbstractSequentialList class.
public Iterator<E> iterator() {
return listIterator();
listIterator() method is implemented in AbstractList class which is parent class for AbstractSequentialList and to sum it up it returns an iterator object which does not use concept of nodes if I'm not mistaken.
public ListIterator<E> listIterator() {
return listIterator(0);
}
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
cursor = index;
}
But listIterator(int index) method IS implemented in LinkedList class and uses concept of nodes.
public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index);
}
private class ListItr implements ListIterator<E> {
private Node<E> lastReturned;
private Node<E> next;
private int nextIndex;
private int expectedModCount = modCount;
so returning to j, is it an iterator from "root" class AbstractList or the implementation LinkedList class is used?
Well, since iterator() returns listIterator(), listIterator() returns listIterator(0), and listIterator(int index) is overridden by LinkedList, LinkedList's iterator() method returns an instance of LinkedList$ListItr.

how to create an immutable iterator?

If I have a Map or a List and get an iterator from it, for example:
var map = new HashMap();
var iterator = map.entrySet().iterator();
if something modifies that map after the fact, will it affect the iterator or is the iterator basically immutable once created?
If it's not immutable, how to create an immutable iterator?
The only valid operations for an iterator are increment and dereference (although the Java Iterator combines the two in its next() method). If you have an unmodifiable iterator, that leaves you only dereferencing. The dereferencing can either give you an object reference, or it can be not valid to dereference because it does not refer to a valid position in the collection.
But those are the same semantics as Optional: an Optional can either be empty or have a valid object reference. So, create an Optional from the Iterator and use that as your "unmodifiable iterator":
private Optional<T> unmodifiableNext(Iterator<T> i)
{
if (i.hasNext()) {
return Optional.ofNullable(i.next());
} else {
return Optional.empty();
}
}
This has the additional benefit that the Optional is no longer tied to the collection, so the collection can be safely changed without changing which object the Optional refers to.
An iterator instance itself would not generally need the concept of mutability/immutability. However, the collection it is iterating over may be intended to be unmodifiable or immutable. Here is a way to disable the ability of an iterator to change the collection. If you return an instance of this class, then the remove() method of the returned iterator is disabled. The class is used by returning UnmodifiableIterator.create(yourIterator).
import java.util.Iterator;
/**
* UnmodifiableIterator, A wrapper around an iterator instance that
* disables the remove method.
*/
public final class UnmodifiableIterator<E> implements Iterator<E> {
/**
* iterator, The base iterator.
*/
private final Iterator<? extends E> iterator;
private UnmodifiableIterator(final Iterator<? extends E> iterator) {
this.iterator = iterator;
}
public static <E> Iterator<E> create(final Iterator<? extends E> iterator) {
if (iterator == null) {
throw new NullPointerException("The iterator can not be null.");
}
return new UnmodifiableIterator<>(iterator);
}
#Override
public boolean hasNext() {
return iterator.hasNext();
}
#Override
public E next() {
return iterator.next();
}
#Override
public void remove() {
throw new UnsupportedOperationException("Iterator.remove() is disabled.");
}
}

What class is directly implementing ListIterator?

What class actually implements the interface ListIterator? I'm studying the Collections API.. and it would seem as though the actual method that returns a ListIterator within the List implementation classes is directly specified in List itself.
The ListIterator interface specifies that actual methods that you would use to manipulate the iterator.. but I am having trouble finding the actual class that implements this.
What class actually -implements- the interface ListIterator that allows the method in the List classes to work?
I'm sure there has to be an implementation class because calling listIterator() itself surely can not return an Interface, there must be something instantiated.
Use the source luke... use the source.
from the source of ArrayList in JDK 8 (1.8.0_45)
public ListIterator<E> listIterator() {
return new ListItr(0);
}
// then line 905
/**
* An optimized version of AbstractList.ListItr
*/
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}
// etc
So the ListIterator returned by ArrayList is a private inner class that implements the interface ListIterator.
You can't instantiate an interface, but you can always create "invisible" private class, which is satisfying interface, but user can't directly see it. For example, LinkedList defines listIterator as:
public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index);
}
private class ListItr implements ListIterator<E> {
private Node<E> lastReturned;
private Node<E> next;
private int nextIndex;
private int expectedModCount = modCount;
ListItr(int index) {
// assert isPositionIndex(index);
next = (index == size) ? null : node(index);
nextIndex = index;
}
// much more
}
This behavior have it's final form in lambdas, in which you won't have any temptation for looking in sources of the passed class.
ListIterator adds functionality for iterating lists API.
This is an usage example:
List<String> l = new ArrayList<String>();
ListIterator<String> it = l.listIterator();
it.next() ...

Can ListIterator safely be susbtituted for Iterator? (Implementing a CopyOnWrite wrapper for List)

I have many instance in code where a Collection, most usually a List is returned from a method and to account for the caller possibly altering that list, a defensive copy is made.
The JDK does not seem to provide a wrapper for this purpose, so I'm trying to roll my own (Note: java.util.concurrent.CopyOnWriteArrayList is not what I'm looking for here).
Schematically, what I'm trying is:
public class CopyOnWriteList<E> extends List<E> {
protected List<E> list;
protected boolean isCopied;
public CopyOnWriteList(List<E> list) {
this.list = list;
}
private void ensureCopy() {
if (!isCopied) {
list = new ArrayList<E>(list);
isCopied = true;
}
}
public E get(int i) {
return list.get(i);
}
public boolean add(E e) {
ensureCopy();
return list.add(e);
}
// ... many more simple methods
}
For most of the API this is simple enough, but looking at java.util.ArrayList I found, that for the method iterator() it returns a different implementation than for listIterator(), although is ListIterator extends its Iterator and it doesn't add any new members.
I wonder if there is a deeper reason behind this - I planned simply to implement iterator() and listIterator() all returning the same type of iterator - a ListIterator. Is there any logical reason why one should not return a ListIterator from the iterator()-method?
ListIterator extends Iterator. So if you return an object that implements ListIterator then it obviously also implements Iterator. But you also can decide to return different object that only implements Iterator, because the implementation could be more effective. The decision is up to you.

How to generate an Iterator from an array of certain object

private SomeObject[] all_objs;
public Iterator<SomeObject> iterator() {
//
}
What is the best way to get an iterator from an array of SomeObject?
EDIT
So there is no way to generate iterator without using the wrappers like ArrayLists or HashSets ?
You could write your own class that implements Iterator<SomeObject>. Simply implement the methods of the interface. If you don't want the users of the iterator from removing items from the array (since it isn't an ArrayList), then throw an UnsupportedOperationException if this method is called.
Of course if you use an ArrayList<SomeObject> then the iterator() method would only have to return the iterator from the ArrayList making your life much easier.
Using the List iterator:
import java.util.List;
import java.util.Arrays;
public <T> Iterator<T> iterator() {
List<T> list = (List<T>) Arrays.asList(all_objs);
return list.iterator();
}
You can also look at the code of java.util.ArrayList. Here is how you should implement it.
T=SomeObject //Your Class
public YourIterable<T> implements Iterable<T>{
//**Iterable** Implementing this interface allows an object
//to be the target of the "foreach" statement.
public Iterator<T> iterator() {
return new Itr();
}
private class Itr implement Iterator<T> {
//Complex Implementation - You have to maintain a Cursor to keep track of
// which record was accessed
boolean hasNext() {
//Returns true if the iteration has more elements.
}
T next() {
//Returns the next element in the iteration.
}
void remove() {//Remove
}
}
}

Categories