文章出处:http://blog.youkuaiyun.com/scarthr/article/details/42371227
我们在最开始接触Java中的容器类List、Map、Collection等就了解到了迭代器Iterator,今天我们就来讲解一下Java中的设计模式之一——迭代器模式。
1. 自己实现List容器
我们先写一个底层用数组实现的自己写的ArrayList容器:
package com.thr.iterator;
public class ArrayList {
Object[] objects = new Object[10];
int index = 0;
public void add(Object o) {
if (index == objects.length) {
// 当数组内对象超过数组长度时,将数组的长度扩大2倍
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;
}
}
定义一个Person类:
package com.thr.iterator;
public class Person {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(int age) {
super();
this.age = age;
}
@Override
public String toString() {
return "Person [age=" + age + "]";
}
}
测试一下这个容器:
package com.thr.iterator;
public class Test {
public static void main(String[] args) {
ArrayList list = new ArrayList();
for (int i = 0; i < 15; i++) {
list.add(new Person(i));
}
System.out.println(list.size());
}
}
可以运行!
然后心情不错,再自己写一个链表结构的LinkedList:
package com.thr.iterator;
public class LinkedList {
private Node head;
private Node tail;
private int size;
public void add(Object o) {
Node node = new Node(o, null);
// 添加元素为第一个时,指定它就是head,同时也是tail。
if (head == null) {
head = node;
tail = node;
}
tail.setNode(node);
tail = node;
size++;
}
public int size() {
return size;
}
}
修改测试代码:
package com.thr.iterator;
public class Test {
public static void main(String[] args) {
LinkedList list = new LinkedList();
for (int i = 0; i < 15; i++) {
list.add(new Person(i));
}
System.out.println(list.size());
}
}
可以运行!
2. 创建Collection接口
这样子写来写去的,它们都含有add方法和size方法,于是我们定义一个接口Collection:
package com.thr.iterator;
public interface Collection {
public void add(Object o);
public int size();
}
然后让ArrayList和LinkedList都实现这个接口,这时测试代码成了:
package com.thr.iterator;
public class Test {
public static void main(String[] args) {
Collection c = new ArrayList();
// Collection c = new LinkedList();
for (int i = 0; i < 15; i++) {
c.add(new Person(i));
}
System.out.println(c.size());
}
}
以后切换容器的时候只需替换Collection所指向子类的对象即可,这就是所谓的面向接口编程。
3. 迭代器Iterator
那么此时问题就来了,如果需要遍历我们的容器该怎么操作呢?一个是数组的容易,一个是链表的容器,该怎么做呢?
这时候我们就需要定义一个标准出来,让所有的容器都来遵循这个标准就可以。
我们创建一个接口Iterator:
package com.thr.iterator;
public interface Iterator {
Object next();
boolean hasNext();
}
在Collection中也定义个iterator方法,返回实现Iterator接口的对象:
package com.thr.iterator;
public interface Collection {
void add(Object o);
int size();
Iterator iterator();
}
修改我们的ArrayList,增加新的方法:
@Override
public Iterator iterator() {
return new ArrayListIterator();
}
private class ArrayListIterator implements Iterator {
private int currentIndex;
@Override
public boolean hasNext() {
boolean flag;
if (currentIndex >= index) {
flag = false;
} else {
flag = true;
}
return flag;
}
@Override
public Object next() {
Object o = objects[currentIndex];
currentIndex++;
return o;
}
}
我们定义了一个内部类ArrayListIterator实现了Iterator接口的两个方法,在ArrayList中实现iterator方法,返回了我们的内部类引用。测试:
Collection c = new LinkedList();
// Collection c = new LinkedList();
for (int i = 0; i < 15; i++) {
c.add(new Person(i));
}
Iterator iterator = c.iterator();
while (iterator.hasNext()) {
Object o = iterator.next();
System.out.println(o + "");
}
遍历成功!
最后同理修改我们的LinkedList,增加新的接口:
@Override
public Iterator iterator() {
return new LinkedListIterator();
}
private class LinkedListIterator implements Iterator {
private int currentIndex;
private Node currentNode;
@Override
public boolean hasNext() {
return !(currentIndex >= size);
}
@Override
public Object next() {
if (currentNode == null) {
currentNode = head;
}
Object o = currentNode.getData();
currentNode = currentNode.getNode();
currentIndex++;
return o;
}
}
测试遍历:
// Collection c = new LinkedList();
Collection c = new LinkedList();
for (int i = 0; i < 15; i++) {
c.add(new Person(i));
}
Iterator iterator = c.iterator();
while (iterator.hasNext()) {
Object o = iterator.next();
System.out.println(o + "");
}
成功!
这么做以来,抽象出来了Collection接口和Iterator接口,让我们以后替换容器类的时候更加的方便,并且在使用Collection做引用时,完全不用考虑各个容器内部是如何实现的,自己在写容器的时候,只需实现规定的接口就可以了。