java设计模式-Iterator

Iterator模式
主要是用在容器的遍历上,其他的地方都不怎么用;理解一下,会用了就可以了;
 

1、背景                    

请动手自己写一个可以动态添加对象的容器;
代码:
ArrayList.java(是自己实现的,不是JDK)
package com.cy.dp.iterator;

public class ArrayList {
    Object[] objects = new Object[10];
    int index = 0;                                        //objects下一个空的位置
    
    /**
     * 如果数组容量已满,这里简单处理,扩容为原来的两倍;
     * sun的做法是有一个加权值,根据原来的容量,加上多少...
     * @param o
     */
    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;
    }
    
}

Cat.java  辅助类:

package com.cy.dp.iterator;

public class Cat {
    private int id;

    public Cat(int id) {
        super();
        this.id = id;
    }
}
View Code

Test.java 测试类:

package com.cy.dp.iterator;

import com.cy.dp.iterator.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        for(int i=0; i<15; i++){
            al.add(new Cat(i));
        }
        System.out.println(al.size());
    
        
    }
}
View Code

 

2.上面容器的底层实现是用数组,下面使用链表来做个容器;

简单解释链表:
每一个链表里面装的都是一个一个的节点,每个节点里面包括两部分内容:1.数据本身 2.指向下一个节点的一个引用;
 
代码:
Node.java:
package com.cy.dp.iterator;

public class Node {
    private Object data;
    private Node next;

    public Node(Object data, Node next) {
        super();
        this.data = data;
        this.next = next;
    }
    
    public Object getData() {
        return data;
    }
    public void setData(Object data) {
        this.data = data;
    }
    public Node getNext() {
        return next;
    }
    public void setNext(Node next) {
        this.next = next;
    }
}
LinkedList.java:
package com.cy.dp.iterator;

public class LinkedList {
    Node head = null;
    Node tail = null;        //最末尾的节点
    int size = 0;            //记录当前链表里面Node个数
    
    public void add(Object o){
        Node n = new Node(o, null);
        if(head==null){
            head = n;
            tail = n;
        }
        tail.setNext(n);
        tail = n;
        size++;
    }

    public int size(){
        return size;
    }
}

Test.java 测试类:

package com.cy.dp.iterator;

import com.cy.dp.iterator.ArrayList;
import com.cy.dp.iterator.LinkedList;

public class Test {
    public static void main(String[] args) {
        //ArrayList al = new ArrayList();
        LinkedList al = new LinkedList();
        
        for(int i=0; i<15; i++){
            al.add(new Cat(i));
        }
        System.out.println(al.size());
    }
}
View Code

 

3.考虑容器的可替换性        

Test类中的容器类可以替换,但是测试方法无须修改;比如LinkedList里面添加元素方法为addObject()的话,那么代码就要重新修改了;
所以有必要对ArrayList和LinkedList对外公开的方法统一起来;
使用接口Collection,面向接口编程;好处是灵活,可扩展;
 
于是就变成了代码:
Collection.java:
package com.cy.dp.iterator;

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

ArrayList.java (实现Collection接口)

package com.cy.dp.iterator;

import com.cy.dp.iterator.Collection;

public class ArrayList implements Collection {
    Object[] objects = new Object[10];
    int index = 0;                                        //objects下一个空的位置
    
    /**
     * 如果数组容量已满,这里简单处理,扩容为原来的两倍;
     * sun的做法是有一个加权值,根据原来的容量,加上多少...
     * @param o
     */
    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;
    }
    
}
View Code

LinkedList.java(实现Collection接口)

package com.cy.dp.iterator;

import com.cy.dp.iterator.Collection;

public class LinkedList implements Collection {
    Node head = null;
    Node tail = null;        //最末尾的节点
    int size = 0;            //记录当前链表里面Node个数
    
    public void add(Object o){
        Node n = new Node(o, null);
        if(head==null){
            head = n;
            tail = n;
        }
        tail.setNext(n);
        tail = n;
        size++;
    }

    public int size(){
        return size;
    }
}
View Code

Test.java测试类:

public class Test {
    public static void main(String[] args) {
        Collection c = new LinkedList();
        
        for(int i=0; i<15; i++){
            c.add(new Cat(i));
        }
        System.out.println(c.size());
    }
}
View Code

 

4.容器的遍历                

因为上面ArrayList的遍历方式和LinkedList的遍历方式不同,遍历方式不统一的话,实现方式一变,代码就得跟着变;
每一种容器都有自己的遍历方式,那么能不能找到一种统一的遍历方式呢?
 
代码:
Iterator接口:
package com.cy.dp.iterator;

public interface Iterator {
    Object next();
    boolean hasNext();
}

Collection接口:

package com.cy.dp.iterator;

public interface Collection {
    void add(Object o);
    int size();
    Iterator iterator();
}

ArrayList.java:

package com.cy.dp.iterator;

import com.cy.dp.iterator.Collection;

public class ArrayList implements Collection {
    Object[] objects = new Object[10];
    int index = 0;                                        //objects下一个空的位置
    
    /**
     * 如果数组容量已满,这里简单处理,扩容为原来的两倍;
     * sun的做法是有一个加权值,根据原来的容量,加上多少...
     * @param o
     */
    @Override
    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++;
    }
    
    @Override
    public int size(){
        return index;
    }
    
    @Override
    public Iterator iterator(){
        return new ArrayListIterator();
    }
    
    private class ArrayListIterator implements Iterator{
        private int currentIndex = 0;
        
        @Override
        public Object next() {
            Object o = objects[currentIndex];
            currentIndex++;
            return o;
        }
        
        @Override
        public boolean hasNext() {
            if(currentIndex >= index) return false;
            else return true;
        }
    }
}

LinkedList.java:

package com.cy.dp.iterator;

import com.cy.dp.iterator.Collection;

public class LinkedList implements Collection {
    Node head = null;
    Node tail = null;        //最末尾的节点
    int size = 0;            //记录当前链表里面Node个数
    
    @Override
    public void add(Object o){
        Node n = new Node(o, null);
        if(head==null){
            head = n;
            tail = n;
        }
        tail.setNext(n);
        tail = n;
        size++;
    }
    
    @Override
    public int size(){
        return size;
    }
    
    //返回一个实现了Iterator接口的匿名类
    @Override
    public Iterator iterator(){
        return new Iterator(){
            Node currentNode = head;
            
            @Override
            public Object next() {
                Object o = currentNode.getData();
                currentNode = currentNode.getNext();
                return o;
            }

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

Test.java 测试类:

public class Test {
    public static void main(String[] args) {
        Collection c = new LinkedList();
        //Collection c = new ArrayList();
        
        for(int i=0; i<15; i++){
            c.add(new Cat(i));
        }
        System.out.println(c.size());
        
        Iterator it = c.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        
    }
}

打印:

15
Cat [id=0]
Cat [id=1]
Cat [id=2]
Cat [id=3]
Cat [id=4]
Cat [id=5]
Cat [id=6]
Cat [id=7]
Cat [id=8]
Cat [id=9]
Cat [id=10]
Cat [id=11]
Cat [id=12]
Cat [id=13]
Cat [id=14]

 

 
 
posted on 2018-06-06 23:07  有点懒惰的大青年  阅读(286)  评论(0编辑  收藏  举报