作为初学者,看到Iterator和IO这里就是一个好大的砍,前几天好好的看了一遍,似乎有了那么点意思,但是还是似懂非懂,不过把现在理解的程度记下来,然后以便将来复习:
迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。从定义可见,迭代器模式是为容器而生。很明显,对容器对象的访问必然涉及到遍历算法。你可以一股脑的将遍历方法塞到容器对象中去;或者根本不去提供什么遍历算法,让使用容器的人自己去实现去吧。这两种情况好像都能够解决问题。然而在前一种情况,容器承受了过多的功能,它不仅要负责自己“容器”内的元素维护(添加、删除等等),而且还要提供遍历自身的接口;而且由于遍历状态保存的问题,不能对同一个容器对象同时进行多个遍历。第二种方式倒是省事,却又将容器的内部细节暴露无遗。
像下面,集合就是一个存放数据的一个容器,完全自己来调用也是可以的,就像是下面的一个500个小孩子的例子:
package itat;
import java.util.*;
public class TestLinkedList {
static int m = 0;
static int n = 500;
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<Integer>();
for(int i = 1;i<n;i++){
list.add(i);
}
while(list.size()>1){
for(int i =0;i<list.size();i++){
m++;
if(m%3 == 0){
m=0;
list.remove(i);
i--;
}
}
}
System.out.println(list.get(0));
}
}
这样完全是用一个循环就可以便利自己的数据,但是链表的复杂的结构和诡异的存储就不能体现的淋漓尽致了:
那么我们可以用一个就给他量身定做的遍历他的东东来遍历他岂不是更好,于是我们用Iterator了:
package itat;
import java.util.*;
public class TestIterator {
private String name ;
private int id;
private double score;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public static void main(String[] args) {
LinkedList list = new LinkedList();
TestIterator t = new TestIterator();
t.setName("李扬扬");
list.add(t.getName());
t.setId(1);
list.add(t.getId());
t.setScore(60.0);
list.add(t.getScore());
t.setName("底向阳");
list.add(t.getName());
t.setId(2);
list.add(t.getId());
t.setScore(70.0);
list.add(t.getScore());
t.setName("底向阳");
list.add(t.getName());
t.setId(2);
list.add(t.getId());
t.setScore(70.0);
list.add(t.getScore());
System.out.println("姓名\t学号\t成绩");
Iterator it = list.iterator();
int i = 0;
while(it.hasNext()){
i++;
System.out.print(it.next());
System.out.print("\t");
if(i==3){
System.out.println();
i=0;
}
}
}
}
用它来实现了一个简单的数据的调用,同样他 也不那么简单,可以像下面一样巧妙的操作链表,详情请见API文档:
集合类基本都有返回Iterator的方法,比如List就由返回Iterator和ListIterator的方法。ListIterator继承Iterator接口。这两个接口最大的不同在与Iterator这能进行顺序遍历,而 ListIterator能进行双向遍历。
package itat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class IteratorTest {
public static void main(String[] args) {
List<String> strList = new ArrayList<String>();
for(int i = 0; i < 3; i ++) {
strList.add("str" + i);
}
Iterator<String> strIterator = strList.iterator();
ListIterator<String> strListIterator = strList.listIterator();
for(; strIterator.hasNext();) {
System.out.println(strIterator.next());
}
System.out.println("------------------------------");
for(; strListIterator.hasNext();) {
System.out.println(strListIterator.next());
}
System.out.println("------------------------------");
for(; strListIterator.hasPrevious();) {
System.out.println(strListIterator.previous());
}
System.out.println("------------------------------");
}
}
结果如下:
str0
str1
str2
------------------------------
str0
str1
str2
------------------------------
str2
str1
str0
------------------------------
与原来定义的好多接口同出一辙,我们断然没有必要自己去在煞费苦心的想一个算法,但是我单单讲的是不用单单的为了这个去想一个高深的算法或者是数据结构,这样一个简单的遍历就可以结果一些问题:诸如TestAccessRandomFile也可以通过seek的移动实现倒叙的遍历,而不是我们再去想怎么去内在的实现,这就是我还似懂非懂的面向对象吧:
package itat;
import java.io.*;
public class TestAccessRandomFile {
public static void main(String [] args){
int arr [] = {1,2,3,4,5,6,7,8,9,10};
try {
RandomAccessFile arf = new RandomAccessFile("D://java//Filetom.dat","rw");
for(int i = 0;i<arr.length;i++){
arf.writeInt(arr[i]);
}
for(int i = arr.length*4-4;i>=0;i-=4){
arf.seek(i);
System.out.print(arf.readInt());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}