Iterator pattern
It provides a way to access each object in a container element, without exposing the internal details of the object.
Iterator pattern structure
1, the iterator role
Responsible for defining access and traverse the elements of the interface
2, the role of specific iterator
Implement iterator interface and to record the current position in the traversal
3, the role of the container
Creating responsible for providing the specific role of the interface iterator
4, the role of specific container
Create specific roles to achieve the iterator interface, the concrete iterator role related to the container structure
Why do we need iterator pattern
Include a simple example, traversing ArrayList, LinkedList, HashSet each element:
1 public static void main(String[] args) { 2 List<Integer> arrayList = new ArrayList<Integer>(); 3 arrayList.add(1); 4 arrayList.add(2); 5 List<Integer> linkedList = new LinkedList<Integer>(); 6 linkedList.add(3); 7 linkedList.add(4); 8 HashSet<Integer> hashSet = new HashSet<Integer>(); 9 hashSet.add(5); 10 hashSet.add(6); 11 Iterator<Integer> iterator = null; 12 iterator = arrayList.iterator(); 13 System.out.println("ArrayList:"); 14 while (iterator.hasNext()) 15 { 16 System.out.print(iterator.next() + "\t"); 17 } 18 System.out.println("\nLinkedList:"); 19 iterator = linkedList.iterator(); 20 while (iterator.hasNext()) 21 { 22 System.out.print(iterator.next() + "\t"); 23 } 24 System.out.println("\nHashSet:"); 25 iterator = hashSet.iterator(); 26 while (iterator.hasNext()) 27 { 28 System.out.print(iterator.next() + "\t"); 29 } 30 }
operation result:
ArrayList: 1 2 LinkedList: 3 4 HashSet: 5 6
Just a combination to achieve the iterable interface that can be used in such a way traversal. Developers do not need to know the details of how to traverse the collection, although a similar method to traverse enough.
Iterable Iterator in Java and
Implements the Iterable interface, it indicates an object that may be iterative; Iterator interface is equivalent to an iterator realized Iterator interface, this is equal to specifically define how the iteration when the object may be iterative. See the definition of interfaces Iterable:
1 public interface Iterable<T> { 2 3 /** 4 * Returns an iterator over a set of elements of type T. 5 * 6 * @return an Iterator. 7 */ 8 Iterator<T> iterator(); 9 }
1 public interface Iterator<E> { 2 /** 3 * Returns {@code true} if the iteration has more elements. 4 * (In other words, returns {@code true} if {@link #next} would 5 * return an element rather than throwing an exception.) 6 * 7 * @return {@code true} if the iteration has more elements 8 */ 9 boolean hasNext(); 10 11 /** 12 * Returns the next element in the iteration. 13 * 14 * @return the next element in the iteration 15 * @throws NoSuchElementException if the iteration has no more elements 16 */ 17 E next(); 18 19 /** 20 * Removes from the underlying collection the last element returned 21 * by this iterator (optional operation). This method can be called 22 * only once per call to {@link #next}. The behavior of an iterator 23 * is unspecified if the underlying collection is modified while the 24 * iteration is in progress in any way other than by calling this 25 * method. 26 * 27 * @implSpec 28 * The default implementation throws an instance of 29 * {@link UnsupportedOperationException} and performs no other action. 30 * 31 * @throws UnsupportedOperationException if the {@code remove} 32 * operation is not supported by this iterator 33 * 34 * @throws IllegalStateException if the {@code next} method has not 35 * yet been called, or the {@code remove} method has already 36 * been called after the last call to the {@code next} 37 * method 38 */ 39 default void remove() { 40 throw new UnsupportedOperationException("remove"); 41 } 42 43 /** 44 * Performs the given action for each remaining element until all elements 45 * have been processed or the action throws an exception. Actions are 46 * performed in the order of iteration, if that order is specified. 47 * Exceptions thrown by the action are relayed to the caller. 48 * 49 * @implSpec 50 * <p>The default implementation behaves as if: 51 * <pre>{@code 52 * while (hasNext()) 53 * action.accept(next()); 54 * }</pre> 55 * 56 * @param action The action to be performed for each element 57 * @throws NullPointerException if the specified action is null 58 * @since 1.8 59 */ 60 default void forEachRemaining(Consumer<? super E> action) { 61 Objects.requireNonNull(action); 62 while (hasNext()) 63 action.accept(next()); 64 } 65 }
Why must implement Iterable interface rather than directly implement Iterator interface?
Iterator core interface methods next () and hasNext () depends on the position of the current iteration iterator. If the direct implementation of the Iterator interface, then the collection object contains data for the current iteration position. When the set is transferred between different methods, since the current iteration is not the preset position, the result next () method will become unpredictable. Unless a further interface to add Iterator reset () method, used to reset the position of the current iteration. But even so, Collection also can only be one current iteration position. The Iterable, each call returns a count of the iterator from scratch, without disturbing each other when multiple iterators.
1 public class ArrayList<E> implements List<E>, Iterator<E>, RandomAccess, Cloneable, Serializable 2 { 3 /** 4 * 序列化ID 5 */ 6 private static final long serialVersionUID = -5786598508477165970L; 7 8 private int size = 0; 9 private transient Object[] elementData = null; 10 11 public E next() 12 { 13 ... 14 } 15 16 public boolean hasNext() 17 { 18 ... 19 } 20 ... 21 }
So the question becomes, if an ArrayList instance is iterated multiple places, next () method, hasNext () it is directly operated ArrayList resources, if I define a position in the ArrayList iteration variable, then call for the differences this iteration variable is shared, thread a iteration when the iteration variable settings become the fifth position, this time to switch to thread B, for thread B is concerned, they begin to traverse this ArrayList from fifth position, simply not from zero, how to properly iteration?
. 1 public class ArrayListIterator the implements the Iterator <E> 2 { . 3 int iteratorPostion = 0 ; . 4 . 5 / ** . 6 * is determined whether there are elements behind . 7 * / . 8 @Override . 9 public Boolean the hasNext () 10 { . 11 IF ((+ iteratorPostion . 1)> size) 12 is return to false ; 13 is return to true ; 14 } 15 16 / ** . 17 * Before returning a reference to the element 18 is * / . 19 @Override 20 is public E Next () 21 is { 22 is return (E) elementData of [iteratorPostion ++ ]; 23 is } 24 ... 25 }
Each time to send back an instance ArrayListIterator out:
1 / * 2 * iterator returns an ArrayList, the element may traverse the ArrayList by the iterator . 3 * / . 4 public the Iterator <E> Iterator () . 5 { . 6 return new new ArrayListIterator (); . 7 }
This ensures that, even while many iterations of this ArrayList, still all over the place from 0 per iteration of this ArrayList instance.
Advantages and disadvantages of the iterator pattern
Iterator pattern advantages:
- It simplifies traversal, to traverse the collection of objects, it is quite troublesome for the array or ordered list, we can still be made through the cursor, but users need to understand very clearly the collection under the premise, traverse the object itself, but for hash table, the user to traverse up more trouble. After the introduction of the iterator method, the user can use it more simple.
- Can provide a variety of ways to traverse, for example, ordered list, we can provide a positive sequence needed to traverse, descending traverse two iterative, the user only needs to get together with us to achieve good iterator, you can easily to collection traversed.
- Good package, users just need to get the iterator can traverse, and for the traversal algorithm then not to care.
Iterator pattern of shortcomings:
- For relatively simple traversal (like array or ordered lists), iterators way to traverse more complicated, you may have the feeling, like ArrayList, we would rather prefer to use a for loop and get methods to traverse the collection.
Overall: iterator pattern is a collection of symbiosis with the dead, in general, as long as we achieve a collection, you need to provide iterators this collection, like java in the Collection, List, Set, Map, etc. these collections have their own iterators. If we are to achieve such a new container, of course, we need to introduce an iterative mode, give us the container to achieve an iterator.