迭代器模式(Iterator Pattern)又叫作游标模式(CursorPattern),它提供一种按顺序访问集合/容器对象元素的方法,而又无须暴露集合内部表示。迭代器模式可以为不同的容器提供一致的遍历行为,而不用关心容器内元素的组成结构,属于行为型设计模式。

    迭代器模式的应用场景:

    • 访问一个集合对象的内容而无须暴露它的内部表示
    • 遍历不同的集合结构提供一个统一的访问接口

    image.png

    java 中提供了两个接口:

    • java.util.Iterable:提供了获取迭代器的方法 iterator()
    • java.util.Iterator:迭代器接口,提供了 hasNext()、next()、remove() 方法

    示例:一个只有 add 和 遍历 的简单容器
    1、链表实现

    1. public class LinkedContainer<E> implements Iterable<E> {
    2. private class Node<E> {
    3. E element;
    4. Node<E> next;
    5. public Node(E element) {
    6. this.element = element;
    7. this.next = null;
    8. }
    9. }
    10. private Node<E> head;
    11. private Node<E> tail;
    12. private int size;
    13. public LinkedContainer() {
    14. this.head = null;
    15. this.tail = null;
    16. this.size = 0;
    17. }
    18. public void add(E element){
    19. Node<E> node = new Node<>(element);
    20. if (head == null) {
    21. head = node;
    22. } else {
    23. tail.next = node;
    24. }
    25. tail = node;
    26. size++;
    27. }
    28. @Override
    29. public Iterator<E> iterator() {
    30. return new ContainerIter();
    31. }
    32. class ContainerIter implements Iterator<E> {
    33. private Node<E> curr;
    34. public ContainerIter() {
    35. this.curr = head;
    36. }
    37. @Override
    38. public boolean hasNext() {
    39. return curr != null;
    40. }
    41. @Override
    42. public E next() {
    43. E res = curr.element;
    44. curr = curr.next;
    45. return res;
    46. }
    47. }
    48. }

    2、数组实现

    1. @SuppressWarnings("unchecked")
    2. public class ArrayContainer<E> implements Iterable<E> {
    3. @Override
    4. public Iterator<E> iterator() {
    5. return new ArrayIter<>();
    6. }
    7. private Object[] elements;
    8. private int size;
    9. public ArrayContainer(int capacity) {
    10. this.size = 0;
    11. elements = new Object[capacity];
    12. }
    13. public ArrayContainer() {
    14. this(16);
    15. }
    16. public void add(E element) {
    17. if (size == elements.length) {
    18. // 动态扩容
    19. elements = Arrays.copyOf(elements, elements.length * 2);
    20. }
    21. elements[size++] = element;
    22. }
    23. private class ArrayIter<E> implements Iterator<E> {
    24. int pos;
    25. @Override
    26. public boolean hasNext() {
    27. return pos < size;
    28. }
    29. @Override
    30. public E next() {
    31. return (E) elements[pos++];
    32. }
    33. }
    34. }

    遍历示例:在 java 中,针对实现了 Iterable 和 Iterator 的类,支持两种遍历方式
    1、原始的方式:

    • 先获取迭代器 iter = Iterable.iterator();
    • 再通过 while(iter.hasNext()){ iter.next(); } 循环进行遍历 ```java LinkedContainer container = new LinkedContainer<>(); container.add(“世界”); container.add(“如此”); container.add(null); container.add(“我么”); container.add(null);

    // 1.获取迭代器 Iterator iterator = container.iterator(); // 2.遍历访问 while (iterator.hasNext()){ System.out.println(iterator.next()); }

    1. 2、使用 foreach 语法糖
    2. - **foreach 不支持在遍历过程中删除元素**
    3. - **iterator 支持在迭代过程中删除元素**
    4. ```java
    5. LinkedContainer<String> container = new LinkedContainer<>();
    6. container.add("世界");
    7. container.add("如此");
    8. container.add(null);
    9. container.add("我么");
    10. container.add(null);
    11. for (String s : container) {
    12. System.out.println(s);
    13. }