Java Iterable 与 Iterator

702 阅读2分钟

如果你想写一个foreach方法,访问List里面的所有对象,你可能会这么写

public static void forEach(List list) {
        int size = list.size();
        for(int i = 0; i < size; i++) {
            out.println(list.get(i));
        }
    }

但实际中,我们不需要这么麻烦,因为所有collection都有一个iterator()方法,在JDK1.4之前这个方法定义在collection接口中的,因此所有collection都有这个方法。

iterator()方法會傳回java.util.Iterator介面的實作物件,這個物件包括了Collection收集的所有物件,你可以使用Iterator的hasNext()看看有無下一個物件,若有的話,再使用next()取得下一個物件。因此,無論是List、Set、Queue或任何Collection,都可以使用以下的forEach()來顯示所收集之物件:

iterator方法会传回java.util.Iterator接口的实例对象,你可以使用hasNext方法看看有没有下一个对象,如果有的话,在使用next取得下一个对象,所以无论通过多态,无论是List,Set,Queue或者任何collection,都可以使用下面这个foreach方法收集对象:

public static void forEach(Collection collection) {
        Iterator iterator = collection.iterator();
        while(iterator.hasNext()) {
            out.println(iterator.next());
        }
    }

在JDK5之後,原先定義在Collection中的iterator()方法,提昇至新的java.util.Iterable父介面,因此在JDK5之後,你可以使用以下的forEach()方法顯示收集的所有物件: 在JDK5之后,原先定义在collection中的iterator方法,提升到新的java.util.Iterable接口中,这样做的好处是,所有实现了iterable接口的对象,都是可迭代的,而之前只有collection是可迭代的。所以在JDK5之后,可以使用下面的foreach方法收集所有的对象:

public static void forEach(Iterable iterable) {
        Iterator iterator = iterable.iterator();
        while(iterator.hasNext()) {
            out.println(iterator.next());
        }
    }

同时由于JDk5之后还引入了增强式的for循环,foreach可以进一步的简化

import java.util.*;

public class ForEach {
    public static void main(String[] args) {
        List names = Arrays.asList("Justin", "Monica", "Irene");
        forEach(names);
        forEach(new HashSet(names)); 
        forEach(new ArrayDeque(names)); 
    }

    public static void forEach(Iterable iterable) {
        for(Object o : iterable) {
            System.out.println(o);
        }
    }
}

实际上,增强式for循环是编译器的蜜糖,实际代码会展开为:

public static void forEach(Iterable iterable) {
    Object o;
    for(Iterator i\$ = iterable.iterator(); i\$.hasNext(); System.out.println(o)) {
        o = i\$.next();
    }
}

可以看到实际还是调用iterator方法。

由于iterable接口的引进,导致所有实现了这个接口的方法,都可以iterator,看下面这个例子:

package Collection;

import java.util.Iterator;

public class IterableString implements Iterable<Character> {
	
	private String original;

    public IterableString(String original) {
        this.original = original;
    }

	public static void main(String[] args) {
		IterableString str = new IterableString("Justin");
    	for(Character c : str) {
            System.out.println(c);
        }
		// TODO Auto-generated method stub

	}

	@Override
	public Iterator<Character> iterator() {
		// TODO Auto-generated method stub
		return new InnerIterator();
	}
	
	private class InnerIterator implements Iterator<Character> {
        private int index;
        public boolean hasNext() {
            return index < original.length();
        }

        public Character next() {
            Character c = original.charAt(index);
            index++;
            return c;
        }

        public void remove() {}
    }

}

查看编译器,我们发现编译器做了这些事:

Character c;
for(Iterator iterator = str.iterator(); iterator.hasNext();
  System.out.println(c))
    c = (Character)iterator.next();