summary
Continue with the previous chapter: Daily class - handwritten ArrayList - Generic , this article will talk about the implementation details of the iterator of ArrayList. Due to space constraints, this article first implements the one-way iterative method iterator(), and the two-way iterative listIterator() will be implemented in the next article.
Iterator mode
Talking about iterator() Before ListIterator(), let's popularize the iterator pattern.
Baidu Encyclopedia gives an introduction: Iterator mode provides a method to sequentially access various elements in an aggregate object (set / array) without exposing the internal representation of the object.
Class diagram
Participation role
Iterator: iterator interface, which defines iterator operation rules. Generally, there are three core methods,
1> Hasnext() determines whether it can be iterated 2> Next () performs an iteration and returns the current element 3> Remove() deletes the iteration to the element
ConcreteIterator: iterator interface implementation class, which implements three methods of interface iteration.
Aggregate: Abstract aggregate object, a collection object that holds data. Iterators traverse the providers of elements, either abstract classes or interfaces. For example: List interface or AbstractList abstract class.
ConcreteAggregate: the implementation of the abstract aggregate object interface (abstract class), which calls the iterator to traverse the elements one by one.
Take JDK as an example:
Iterator iterator
To implement the iterator() method, the above iterator pattern structure should be established:
MyIterator
/** * Iterator interface: defining iteration rules */ public interface MyIterator<E> { /** * Judge whether there is a next element (judge whether it can be iterated) * @return */ boolean hasNext(); /** * Get current iteration to element (execute next iteration element) * @return */ E next(); /** * Deletes the element to which the current iteration is applied */ void remove(); }
The MyIterator interface defines the rules of iterators. There are at least three core methods of iterators: hasNext, next and remove.
Operation diagram
When next() is executed, cursor will automatically move down
Note: there is another way to understand:
The cursor is located in front of the first element. Each time you move it, you skip one element. Personally, I think there is no difference in operation.
MyItr
It is defined inside the MyArrayList class and is not exposed
public class MyArrayList<E> { /** * MyArrayList Class internal definition private internal class MyItr * Objective: to implement the iterator corresponding to hidden MyArrayList * MyArrayList The iterative interface can be exposed mainly through the iterator method. */ private class MyItr implements MyIterator<E>{ //Cursor (index) starts at 0 private int cursor; @Override public boolean hasNext() { //As long as you don't iterate to the end, you can iterate all the time return cursor != size; } @Override public E next() { //During iteration, if the cursor exceeds the total number, an error is reported if (cursor >= size) throw new NoSuchElementException(); //++Indicates that next is the next element return (E) elementData[cursor++]; } @Override public void remove() { //In the above, if the remove operation is called immediately without executing next first, it will prompt illegal operation if (cursor < 1){ throw new IllegalStateException("Please execute first next method"); } //The cursor is still within the operational range if(cursor <= size){ //After the next method, the cursor executes with the next element. If you want to delete, delete the current element //The cursor returns to the previous value MyArrayList.this.remove(cursor -1); //After deletion, the size-1 in the collection and the right should also be synchronized with - 1 cursor--; } } } }
Define the iterator method in the MyArrayList class and provide the operation object of the iterator for iteration
public class MyArrayList<E> { ..... /** * Expose iterator methods for manipulating collection iterators * Note that interface polymorphism is used here to effectively hide the implementation details of MyItr private inner class * @return */ public MyIterator<E> iterator(){ return new MyItr(); } .... }
Iterative testing
public class App{ public static void main(String[] args) { MyArrayList<String> list = new MyArrayList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); MyIterator<String> iterator = list.iterator(); while (iterator.hasNext()){ System.out.println(list); iterator.next(); iterator.remove(); System.out.println(list); } } }
To print well, override the toString method
public String toString() { MyIterator<E> it = iterator(); if (! it.hasNext()){ return "[]"; } StringBuilder sb = new StringBuilder(); sb.append('['); for (;;) { E e = it.next(); sb.append(e); if (! it.hasNext()){ return sb.append(']').toString(); } sb.append(',').append(' '); } }
[a, b, c, d] [b, c, d] [b, c, d] [c, d] [c, d] [d] [d] []
At this point, the iterator function of the MyArrayList class is implemented.