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;
}
}
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()); }
}
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());
}
}
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;
} }
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;
}
}
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());
}
}
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]