iterator与iterable
如果想用foreach遍历自定义类的集合,自定义类通常需要实现implement iterable接口. 该接口定义了Iterator<T> iterator()方法. 有些时候这个iterator方法可以供用类里面的集合属性.iterator()返回.
public class Teacher implements Iterable{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Iterator iterator() {
return new Itr();
}
public static void main(String[] args) {
Teacher t = new Teacher();
t.setName("aaaaaaa");
t.setAge(23);
for (Object o : t) {
System.out.println(o.toString());
}
}
private class Itr implements Iterator{
private int cursor=0; // 属性的索引
private Field[] fields = Teacher.class.getDeclaredFields(); // 属性的数组
public boolean hasNext() {
return cursor!=(Teacher.class.getDeclaredFields().length);
}
public Object next() {
Object o=null;
try{
fields[cursor].setAccessible(true); // 让内部类可以访问外部类的私有属性的值
o = fields[cursor].getName()+" "+fields[cursor].get(Teacher.this);
cursor++;
}catch(Exception e){
System.out.println(e);
}
return o;
}
public void remove() {
// TODO Auto-generated method stub
}
}
}
import java.util.Iterator;
//测试类
public class Exec {
public static void main(String[] args) throws Exception {
// 创建学生集合类
Students students = new Students(10);
// 通过for each语句迭代循环学生集合类的每个元素
for (Object obj : students) {
Student stu = (Student) obj;
System.out.println(stu.getSid() + ":" + stu.getName());
}
}
}
// 支持for each迭代循环的学生集合类
class Students implements Iterable {
// 存储所有学生类的数组
private Student[] stus;
// 该构造函数可以生成指定大小的学生类变量数组,并初始化该学生类变量数组
public Students(int size) {
stus = new Student[size];
for (int i = 0; i < size; i++) {
stus[i] = new Student(String.valueOf(i), "学生" + String.valueOf(i));
}
}
// 实现Iterable接口的重要方法,返回自定义的迭代类变量
public Iterator iterator() {
return new StudentIterator();
}
// 实现Iterator接口的私有内部类,外界无法直接访问
private class StudentIterator implements Iterator {
// 当前迭代元素的下标
private int index = 0;
// 判断是否还有下一个元素,如果迭代到最后一个元素就返回false
public boolean hasNext() {
return index != stus.length;
}
// 返回当前元素数据,并递增下标
public Object next() {
return stus[index++];
}
// 这里不支持,抛出不支持操作异常
public void remove() {
throw new UnsupportedOperationException();
}
}
}
// 学生类
class Student {
// 学生学号
private String sid;
// 学生姓名
private String name;
// 默认构造函数
public Student() {
}
// 支持属性值初始化的构造函数
public Student(String sid, String name) {
setSid(sid);
setName(name);
}
// 学生学号的读取函数
public String getSid() {
return sid;
}
// 学生学号的设置函数
public void setSid(String sid) {
this.sid = sid;
}
// 学生姓名的读取函数
public String getName() {
return name;
}
// 学生姓名的设置函数
public void setName(String name) {
this.name = name;
}
// 格式化字符信息输出
public String toString() {
return this.sid + ":" + this.name;
}
}
为什么一定要去实现Iterable这个接口呢? 为什么不直接实现Iterator接口呢?
看一下JDK中的集合类,比如List一族或者Set一族,
都是实现了Iterable接口,但并不直接实现Iterator接口。
仔细想一下这么做是有道理的。因为Iterator接口的核心方法next()或者hasNext()
是依赖于迭代器的当前迭代位置的。
如果Collection直接实现Iterator接口,势必导致集合对象中包含当前迭代位置的数据(指针)。
当集合在不同方法间被传递时,由于当前迭代位置不可预置,那么next()方法的结果会变成不可预知。
除非再为Iterator接口添加一个reset()方法,用来重置当前迭代位置。
但即时这样,Collection也只能同时存在一个当前迭代位置。
而Iterable则不然,每次调用都会返回一个从头开始计数的迭代器。
多个迭代器是互不干扰的