迭代器模式

迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示, 主要用于容器和容器遍历

数据结构中的物理结构只有两种:

第一种: 连续存储, 数组

第二种: 不连续存储, 链表 每个储存位置不但储存当前值, 还储存一个内存地址, 指向下个值的地址

数组演示

package com.cyc.design.iterator.v1;

/**
 * 构建一个容器,可以添加对象
 */

public class Main {
    public static void main(String[] args) {
        ArrayList_ list = new ArrayList_();
        for(int i=0; i<15; i++) {
            list.add(new String("s" + i));
        }
        System.out.println(list.size());
    }
}


/**
 * 相比数组,这个容器不用考虑边界问题,可以动态扩展
 */
class ArrayList_ {
    Object[] objects = new Object[10];
    //objects中下一个空的位置在哪儿,或者说,目前容器中有多少个元素
    private int index = 0;
    public void add(Object o) {
        if(index == objects.length) {
            //每次扩容两倍
            Object[] newObjects = new Object[objects.length*2];
            System.arraycopy(objects, 0, newObjects, 0, objects.length);
            objects = newObjects;
        }

        objects[index] = o;
        index ++;
    }

    public int size() {
        return index;
    }
}

链表演示

package com.cyc.design.iterator.v2;

/**
 * v1:构建一个容器,可以添加对象
 * v2:用链表来实现一个容器
 */

public class Main {
    public static void main(String[] args) {
        LinkedList_ list = new LinkedList_();
        for(int i=0; i<15; i++) {
            list.add(new String("s" + i));
        }
        System.out.println(list.size());
    }
}


/**
 * 相比数组,这个容器不用考虑边界问题,可以动态扩展
 */
class LinkedList_ {
    Node head = null;
    Node tail = null;
    //目前容器中有多少个元素
    private int size = 0;

    public void add(Object o) {
        Node n = new Node(o);
        n.next = null;

        if(head == null) {
            head = n;
            tail = n;
        }

        tail.next = n;
        tail = n;
        size++;
    }

    private class Node {
        //储存的值
        private Object o;
        //下一个节点的地址
        Node next;

        public Node(Object o) {
            this.o = o;
        }
    }

    public int size() {
        return size;
    }
}

相互替换

参照java的ArrayList和LinkedList让两者都实现自定义的Collection_接口

Collection_

package com.cyc.design.iterator.v3;

public interface Collection_ {
    void add(Object o);
    int size();
}

ArrayList_

package com.cyc.design.iterator.v3;


/**
 * 相比数组,这个容器不用考虑边界问题,可以动态扩展
 */
class ArrayList_ implements Collection_ {
    Object[] objects = new Object[10];
    //objects中下一个空的位置在哪儿,或者说,目前容器中有多少个元素
    private int index = 0;
    public void add(Object o) {
        if(index == objects.length) {
            Object[] newObjects = new Object[objects.length*2];
            System.arraycopy(objects, 0, newObjects, 0, objects.length);
            objects = newObjects;
        }

        objects[index] = o;
        index ++;
    }

    public int size() {
        return index;
    }
}
package com.cyc.design.iterator.v3;

/**
 * 相比数组,这个容器不用考虑边界问题,可以动态扩展
 */
class LinkedList_ implements Collection_ {
    Node head = null;
    Node tail = null;
    //目前容器中有多少个元素
    private int size = 0;

    public void add(Object o) {
        Node n = new Node(o);
        n.next = null;

        if(head == null) {
            head = n;
            tail = n;
        }

        tail.next = n;
        tail = n;
        size++;
    }

    private class Node {
        private Object o;
        Node next;

        public Node(Object o) {
            this.o = o;
        }
    }

    public int size() {
        return size;
    }
}

Main方法

package com.cyc.design.iterator.v3;

/**
 * v1:构建一个容器,可以添加对象
 * v2:用链表来实现一个容器
 * v3:添加容器的共同接口,实现容器的替换
 */

public class Main {
    public static void main(String[] args) {
        Collection_ list = new ArrayList_();
        for(int i=0; i<15; i++) {
            list.add(new String("s" + i));
        }
        System.out.println(list.size());
    }
}



容器遍历

package com.cyc.design.iterator.v4;

/**
 * v1:构建一个容器,可以添加对象
 * v2:用链表来实现一个容器
 * v3:添加容器的共同接口,实现容器的替换
 * v4:如何对容器遍历呢?
 */

public class Main {
    public static void main(String[] args) {
        Collection_ list = new ArrayList_();
        for(int i=0; i<15; i++) {
            list.add(new String("s" + i));
        }
        System.out.println(list.size());


        ArrayList_ al = (ArrayList_)list;
        for(int i=0; i<al.size(); i++) {
            //如果用这种遍历方式,就不能实现通用了
        }
    }
}

但是这种遍历方式不够灵活, 不是通用的,

解决方案: 让每种容器去实现自己的遍历方式

自己的遍历方式

  • Collection_
package com.cyc.design.iterator.v5;

public interface Collection_ {
    void add(Object o);

    int size();

    Iterator_ iterator();
}

  • Iterator_
package com.cyc.design.iterator.v5;

public interface Iterator_ {
    //判断是否有下一个值
    boolean hasNext();

    //下一个值
    Object next();
}

  • LinkedList_
package com.cyc.design.iterator.v5;

/**
 * 相比数组,这个容器不用考虑边界问题,可以动态扩展
 */
class LinkedList_ implements Collection_ {
    Node head = null;
    Node tail = null;
    //目前容器中有多少个元素
    private int size = 0;

    public void add(Object o) {
        Node n = new Node(o);
        n.next = null;

        if (head == null) {
            head = n;
            tail = n;
        }

        tail.next = n;
        tail = n;
        size++;
    }

    private class Node {
        private Object o;
        Node next;

        public Node(Object o) {
            this.o = o;
        }
    }

    public int size() {
        return size;
    }

    @Override
    public Iterator_ iterator() {
        return new LinkedListIterator();
    }

    private class LinkedListIterator implements Iterator_{

        private Node currentNode = head;

        @Override
        public boolean hasNext() {
            if (currentNode.next == null) {
                return false;
            }
            return true;
        }

        @Override
        public Object next() {
            Node node;
            if (currentNode == head) {
                node = head;
            } else {
                node = currentNode.next;
            }
            currentNode = currentNode.next;
            return node.o;
        }
    }
}

  • ArrayList_
package com.cyc.design.iterator.v5;


/**
 * 相比数组,这个容器不用考虑边界问题,可以动态扩展
 */
class ArrayList_ implements Collection_ {
    Object[] objects = new Object[10];
    //objects中下一个空的位置在哪儿,或者说,目前容器中有多少个元素
    private int index = 0;

    public void add(Object o) {
        if (index == objects.length) {
            Object[] newObjects = new Object[objects.length * 2];
            System.arraycopy(objects, 0, newObjects, 0, objects.length);
            objects = newObjects;
        }

        objects[index] = o;
        index++;
    }

    public int size() {
        return index;
    }

    @Override
    public Iterator_ iterator() {
        return new ArrayListIterator();
    }

    private class ArrayListIterator implements Iterator_ {

        private int currentIndex = 0;

        @Override
        public boolean hasNext() {
            if (currentIndex >= index) return false;
            return true;
        }

        @Override
        public Object next() {
            Object o = objects[currentIndex];
            currentIndex++;
            return o;
        }
    }


}

main方法

package com.cyc.design.iterator.v5;

/**
 * v1:构建一个容器,可以添加对象
 * v2:用链表来实现一个容器
 * v3:添加容器的共同接口,实现容器的替换
 * v4:如何对容器遍历呢?
 * v4:用一种统一的遍历方式,要求每一个容器都要提供Iterator的实现类
 * 作业:实现LinkedList的Iterator
 */

public class Main {
    public static void main(String[] args) {
        Collection_ list = new ArrayList_();
        for (int i = 0; i < 15; i++) {
            list.add(new String("s" + i));
        }
        System.out.println(list.size());

        //这个接口的调用方式:
        Iterator_ it = list.iterator();
        while (it.hasNext()) {
            Object o = it.next();
            System.out.println(o);
        }
    }
}

泛型版迭代

  • Collection_
package com.cyc.design.iterator.v7;

public interface Collection_<E> {
    void add(E o);
    int size();

    Iterator_ iterator();
}

  • Iterator_
package com.cyc.design.iterator.v7;

public interface Iterator_<E> { //Element //Type //K //Value V Tank
    boolean hasNext();

    E next(); //Tank next() Iterator_<Tank> it = ... Tank t = it.next();
}

  • ArrayList_
package com.cyc.design.iterator.v7;


/**
 * 相比数组,这个容器不用考虑边界问题,可以动态扩展
 */
class ArrayList_<E> implements Collection_<E> {
    E[] objects = (E[])new Object[10];
    //objects中下一个空的位置在哪儿,或者说,目前容器中有多少个元素
    private int index = 0;
    public void add(E o) {
        if(index == objects.length) {
            E[] newObjects = (E[])new Object[objects.length*2];
            System.arraycopy(objects, 0, newObjects, 0, objects.length);
            objects = newObjects;
        }

        objects[index] = o;
        index ++;
    }

    public int size() {
        return index;
    }

    @Override
    public Iterator_<E> iterator() {
        return new ArrayListIterator();
    }

    private class ArrayListIterator<E> implements Iterator_<E> {

        private int currentIndex = 0;

        @Override
        public boolean hasNext() {
            if(currentIndex >= index) return false;
            return true;
        }

        @Override
        public E next() {
            E o = (E)objects[currentIndex];
            currentIndex ++;
            return o;
        }
    }


}

  • Main
package com.cyc.design.iterator.v7;

/**
 * v1:构建一个容器,可以添加对象
 * v2:用链表来实现一个容器
 * v3:添加容器的共同接口,实现容器的替换
 * v4:如何对容器遍历呢?
 * v4:用一种统一的遍历方式,要求每一个容器都要提供Iterator的实现类
 *    作业:实现LinkedList的Iterator
 * v6:JDK的容器实现
 * v7:实现泛型版本
 */

public class Main {
    public static void main(String[] args) {
        Collection_<String> list = new ArrayList_<>();
        for(int i=0; i<15; i++) {
            list.add(new String("s" + i));
        }
        System.out.println(list.size());

        //这个接口的调用方式:
        Iterator_<String> it = list.iterator();
        while(it.hasNext()) {
            String o = it.next();
            System.out.println(o);
        }
    }
}



JDK的迭代器

在这里插入图片描述

package com.cyc.design.iterator.v6;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * v1:构建一个容器,可以添加对象
 * v2:用链表来实现一个容器
 * v3:添加容器的共同接口,实现容器的替换
 * v4:如何对容器遍历呢?
 * v4:用一种统一的遍历方式,要求每一个容器都要提供Iterator的实现类
 *    作业:实现LinkedList的Iterator
 * v6:JDK的容器的Iterator
 */

public class Main {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        for(int i=0; i<15; i++) {
            c.add(new String("s" + i));
        }

        Iterator it = c.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

点击ArrayList进入源码

在这里插入图片描述

在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐