遍历内容
23种设计模式之一,行为模式之一,主要用在容器遍历中。返回一个iterator即可遍历对象
优缺点
一般来说,容器的自动的增删改由容器本身确定,而去实现遍历,第一种:有容器本身决定,第二种:由调用者决定。这样虽然都可以实现遍历,但是容易引起程序的混淆,一旦添加或者删除容器也要保存遍历状态,容易出错
把容器的遍历交给一个Iterator来做,屏蔽聚合对象中的容器实现细节,按顺序对集合进行访问。
把容器的访问委托给Iterator,进行遍历。
模拟Collection
package com.Iterator;
public interface Collection {
void add(Object object);
int size();
}
模拟Iterator
public interface Iterator {
Object next();
boolean hasNext();
}
模拟 ArrayList
package com.Iterator;
import com.Iterator.Collection;;
/**
*
* 自定义一个list集合类
*/
public class ArrayList implements Collection{
private Object[] object;
public Object[] getObject() {
return object;
}
public void setObject(Object[] object) {
this.object = object;
}
public ArrayList() {
super();
object = new Object[10];
}
int index = 0;
public void add(Object obj){
if(index == object.length){
Object[] newObject = new Object[object.length *2];
System.arraycopy(object, 0, newObject, 0, object.length);
object = newObject;
}
object[index] = obj;
index ++;
}
public int size(){
return index;
}
public Iterator iterator(){
return new ArrayListIterator();
}
//实现内部类
private class ArrayListIterator implements Iterator{
private int cuurentIndex = 0;
public Object next() {
Object o = object[cuurentIndex];
cuurentIndex++;
return o;
}
@Override
public boolean hasNext() {
if(cuurentIndex >= index){
return false;
}
return true;
}
}
}
模拟 LinkedList
package com.Iterator;
public class LinkedList {
private Node head;
private Node tail;
int index = 0;
public void add(Object obj){
Node n = new Node(obj, null);
if(head == null){
head = n;
tail = n;
return;
}
tail.setNext(n);
tail = n;
index++;
}
public int size(){
return index;
}
//返回一个iterator
public Iterator iterator(){
return new LinkedListIterator();
}
//内部实现类
private class LinkedListIterator implements Iterator{
int currentIndex = 0;
@Override
public Object next() {
Object o = null;
if(head == null)
o = head;
o = head.getNext();
currentIndex++;
return o;
}
@Override
public boolean hasNext() {
if(currentIndex != 0){
return false;
}
return true;
}
}
}
----------
//Node
package com.Iterator;
public class Node {
private Object node ;
private Node next;
public Node(Object node, Node next) {
super();
this.node = node;
this.next = next;
}
public Object getNode() {
return node;
}
public void setNode(Object node) {
this.node = node;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
@Override
public String toString() {
return "Node [node=" + node + ", next=" + next + "]";
}
}
在这里为链表结构做一个补充
- 第一次添加的链表head和tail: 第一次添加时,head和tail都指向同一个对象,
这个时候就应该返回了,我们已经设置好头部和尾部了
-第二次添加时,在第一次设置头部和尾部都指向同一个对象,所以在tail.setNext(n),head也已经改变了,head的next也指向n可,再把尾部tail的指向放到n中(这里为n做一个特别说明,因为之前呢head的next也指向n,所以tail的指向n,可以看作是head头部的next的指向与tail指向的n到最后都指向同一个对象,也可以说tail指向head的next),最后把tail的指向放到n中(n为一个Node,),
- 注意看变化,在tail的setNext(n)中,tail已经与head都指向同一个对象,这个时候已经改变head的next了,这时在吧tai指向head的next,就形成一个完整的链表结构
- 梳理一下:head的next和tail都指向同一个对象,改变tail就等于改变head的next,只不过这个改变是隐藏的,tail.setNext可以看作是head的next.setNext,最后在吧tail指向head的next指向的对象,下次的tail,也就是head的next了。
TestList
import com.Iterator.ArrayList;
import com.Iterator.LinkedList;;
public class TestList {
public static void main(String[] args) {
LinkedList list = new LinkedList();
for(int i= 0;i < 10;i++){
list.add(i);
}
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.println (iterator.next().toString());
}
System.out.println(list.size());
}
}