Detailed description of Iterable and Iterator in java

Source: Internet
Author: User
Keywords Java iterators iterable interface
Tags java java iterators iterable interface iterator interface

In Java, we can traverse the List collection in the following ways:


List<Integer> list = new ArrayList<>();
list.add(5);
list.add(23);
list.add(42);
for (int i = 0; i < list.size(); i++) {
    System.out.print(list.get(i) + ",");
}

Iterator it = list.iterator();
while (it.hasNext()) {
    System.out.print(it.next() + ",");
}

for (Integer i : list) {
    System.out.print(i + ",");
}
The first is the normal for loop, the second is the iterator traversal, and the third is the for each loop. The latter two methods involve iterator and iterable objects in Java. Let's take a look at the differences between these two objects and how to implement for each loop in a custom class.


Iterator and Iterable
Iterator is an iterator object in Java, which is the underlying dependency that can iterate over a collection like List. The iterable interface defines a method for returning an iterator, which is equivalent to encapsulation of the iterator, and classes that implement the iterable interface can support for each loop.

Iterator interior details
The main methods of the Iterator interface in jdk are as follows:

public interface Iterator<E> {
    boolean hasNext();
    E next();
}
Iterator defines the method of iterative access to the collection through the above two methods, and the specific implementation depends on different implementation classes. The concrete collection class implements the methods in the Iterator interface to implement iteration.

It can be found that the Iterator interface is not implemented in the List, but the Iterable interface is implemented. Further observation of the source code of the Iterable interface reveals that it just returns an Iterator object.
public interface Iterable<T> {
  Iterator<T> iterator();
}
So we can iterate over the List in the following way (by calling the iterator() method)



Iterator it = list.iterator();
while (it.hasNext()) {
    System.out.print(it.next() + ",");
}
The For each loop can also be used to implement the Iterable interface.

For each principle
In fact, the for each loop is also dependent on the Iterator iterator, but the syntax sugar provided by Java, the Java compiler will convert it into Iterator iterator traversal. We decompile the following for each loop:



for (Integer i : list) {
       System.out.println(i);
   }
After decompilation:
Integer i;
for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(i)){
        i = (Integer)iterator.next();        
    }
You can see that Java's for each enhancement loop is implemented through an iterator iterator.

In-depth discussion of the relationship between Iterable and Iterator
There is a question, why not directly put the hasNext(), next() methods on the Iterable interface, and other classes can be implemented directly?

The reason is that some collection classes may have more than one traversal method. The class that implements Iterable can implement multiple Iterator inner classes, such as ListItr and DescendingIterator in the LinkedList, which implements two-way traversal and reverse order traversal. This is more flexible by returning different Iterators to implement different traversal methods. If you merge the two interfaces, you can't return a different Iterator implementation class. ListItr related source code is as follows:
public ListIterator<E> listIterator(int index) {
        checkPositionIndex(index);
        return new ListItr(index);
    }

    private class ListItr implements ListIterator<E> {
        ...
        ListItr(int index) {
            // assert isPositionIndex(index);
            next = (index == size) ? null : node(index);
            nextIndex = index;
        }

        public boolean hasNext() {
            return nextIndex < size;
        }
        ...

As shown above, you can return an iterator iterator by calling the list.listIterator() method (list.iterator() is just its default implementation)

DescendingIterator source code is as follows:

public Iterator<E> descendingIterator() {
        return new DescendingIterator();
    }
    private class DescendingIterator implements Iterator<E>     {
        private final ListItr itr = new ListItr(size());
        public boolean hasNext() {
            return itr.hasPrevious();
        }
        public E next() {
            return itr.previous();
        }
        public void remove() {
            itr.remove();
        }
    }
This iterator can also be used via list.descendingIterator().

Implement your own iterator
We now have a custom class ArrayMap, now if we do it for each traversal:

ArrayMap<String, Integer> am = new ArrayMap<>();
am.put("hello", 5);
am.put("syrups", 10);

for (String s: am) {
   System.out.println(s);
}
Since we didn't implement the hashNext and next abstract methods, we can't traverse them.

Custom iterator class
We first customize an iterator class to implement the hashNext and next methods, and use it as an inner class of ArrayMap. The relevant code is as follows:
public class KeyIterator implements Iterator<K> {
        private int ptr;

        public KeyIterator() {
            ptr = 0;
        }

        @Override
        public boolean hasNext() {
            return (ptr != size);
        }

        @Override
        public K next() {
            K returnItem = keys[ptr];
            ptr += 1;
            return returnItem;
        }
    }
It can be seen that the traversal rule we specified in next is traversed according to the key value of ArrayMap. With the above iterator class, we can iterate over it externally using the iterator method. The traversal code is as follows:

ArrayMap<String, Integer> am = new ArrayMap<>();
am.put("hello", 5);
am.put("syrups", 10);
ArrayMap.KeyIterator ami = am.new KeyIterator();
while (ami.hasNext()) {
    System.out.println(ami.next());
}
As shown above, iterative access is done by creating a KeyIterator object (note how the external class creates the inner class object).

Support for each loop
It is not yet possible to support for each loop access, because we have not implemented the iterable interface, first implement the Iterable interface in ArrayMap:
public class ArrayMap<K, V> implements Iterable<K> {

    private K[] keys;
    private V[] values;
    int size;

    public ArrayMap() {
        keys = (K[]) new Object[100];
        values = (V[]) new Object[100];
        size = 0;
    }
  ....
}
Then override the iterator() method and return our own iterator object (iterator)

@Override
    public Iterator<K> iterator() {
        return new KeyIterator();
    }
Note that our custom KeyIterator class must implement the Iterator interface, otherwise the types returned in the iterator() method will not match.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.