【Java程式設計】foreach支援集合、Collection、Iterable遍歷原因分析
阿新 • • 發佈:2019-01-07
1、Collection、AbstractCollection、Iterable關係
Iterator是一個介面public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
Iterable是一個介面
public interface Iterable<T> {
Iterator<T> iterator();
}
AbstractCollection抽象類實現了Collection介面
Collection介面繼承了Iterable介面public abstract class AbstractCollection implements Collection {}
public interface Collection extends Iterable{}
關係圖如下:
分析:
1、foreach迴圈支援對Iterable類(實現了Iterable介面)的遍歷,該結論在本blog第3節得到論證; 2、Collection介面繼承Iterable介面,foreach支援對實現了Collection介面例項類(ArrayList,LinkedList,HashSet,TreeSet,LinkedHashSet)的遍歷,該結論已在《【Java程式設計】Foreach對陣列、Collection物件、Iterable物件》2、使用繼承AbstractCollection類來建立一個Collection的實現(該Collection實現類支援foreach遍歷)
你要實現一個不是Collection的外部類時,由於讓它去實現Collection介面可能非常困難,此時使用AbstractCollection就會變得相當吸引人;AbstractCollection提供了Collection的預設實現,使得你可以建立AbstractCollection的子類,而其中沒有不必要的程式碼重複,不過繼承AbstractCollection來實現Collection需要強制實現iterator()和size(),以便提供AbstractCollection沒有實現但是AbstractCollection中的其他方法會使用的方法;
package com.andieguo.iterabledemo;
import java.util.AbstractCollection;
import java.util.Iterator;
import com.andieguo.collectiondemo.Book;
public class CollectionSequence<T> extends AbstractCollection<T> {
private T[] array = null;
public CollectionSequence(T[] t){
this.array = t ;
}
@Override
public Iterator<T> iterator() {
// TODO Auto-generated method stub
return new Iterator<T>(){
private int index = 0;
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return index < array.length;
}
@Override
public T next() {
// TODO Auto-generated method stub
return array[index++];
}
@Override
public void remove() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}};
}
@Override
public int size() {
// TODO Auto-generated method stub
return array.length;
}
public static void main(String[] args) {
printObject(new String[]{"HELLO","EVERYBODY","WELCOME"});
printObject(new Integer[]{1,2,3,4,5,6});
printObject(new Book[]{new Book("數學"),new Book("英語")});
}
public static void printObject(Object[] t) {
System.out.println("-------------使用foreach輸出-----------------");
CollectionSequence<Object> cs = new CollectionSequence<Object>(t);
for(Object object:cs){
System.out.print(object+" ");
}
System.out.println("\n-----------使用iterator輸出----------------");
Iterator<Object> it = cs.iterator();
while(it.hasNext()){
System.out.print(it.next()+" ");
}
System.out.println();
}
}
3、使用實現Iterable介面來實現適用於foreach遍歷的自定義類。
Java SE5引入了Iterable介面,該介面包含一個能夠產生Iterator的iterator()方法,並且Iterable介面被foreach用來在序列中移動。因此你建立了任何實現Iterable的自定義類,都可以將它用於foreach語句中。
package com.andieguo.iterabledemo;
import java.util.Iterator;
public class IterablerClass<T> implements Iterable<T>{
private T[] array = null;
public IterablerClass(T[] t){
this.array = t ;
}
@Override
public Iterator<T> iterator() {
// TODO Auto-generated method stub
return new Iterator<T>() {
private Integer index = 0;
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return index<array.length;
}
@Override
public T next() {
// TODO Auto-generated method stub
return array[index++];
}
@Override
public void remove() {
// TODO Auto-generated method stub
}
};
}
public static void main(String[] args) {
IterablerClass<String> iterablerClass = new IterablerClass<String>(new String[]{"武漢","深圳","上海","北京","重慶"});
System.out.println("-------------使用foreach輸出-----------------");
for(String s:iterablerClass){
System.out.print(s+" ");
}
System.out.println("\n-----------使用iterator輸出----------------");
Iterator<String> it = iterablerClass.iterator();
while(it.hasNext()){
System.out.print(it.next()+" ");
}
}
}
4、使用介面卡設計模式為Iteratable類(實現了Iterable介面)新增更多的遍歷方法。
如果你現有一個Iteratable類(實現了Iterable介面),你想要新增一種或多種在foreach語句中使用這個類的方法,如果直接繼承這個類,並覆蓋iterator()方法,你只能替代現有的方法,不能實現選擇。一種解決方案是使用介面卡設計模式,當我們有一個介面並需要另外一個介面時,編寫介面卡可以輕鬆解決問題。這裡我們希望在預設向前迭代的基礎上,新增產生反向迭代的能力,只需新增一個能夠產生Iterable物件的方法,該物件可以用於foreach語句。
package com.andieguo.iterabledemo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
public class ReversibleArrayList<T> extends ArrayList<T> {
private static final long serialVersionUID = 2843552489593809340L;
public ReversibleArrayList(Collection<T> c){
super(c);
}
/**
* 注意區別new Iterable<T>方法與new Iterator<T>()方法
* 使用Iterable能夠適用於foreach。使用Iterator能適用於while迴圈迭代
* @return
*/
public Iterable<T> reversed(){
return new Iterable<T>(){
@Override
public Iterator<T> iterator() {
// TODO Auto-generated method stub
return new Iterator<T>() {
int current = size()-1;//size()是父類ArrayList裡的方法
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return current > -1;
}
@Override
public T next() {
// TODO Auto-generated method stub
return get(current--);
}
@Override
public void remove() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
};
}};
}
public static void main(String[] args) {
ReversibleArrayList<String> ral = new ReversibleArrayList<String>(Arrays.asList("one two three four five six".split(" ")));
for(String str:ral){
System.out.print(str+" ");
}
System.out.println();
for(String str:ral.reversed()){
System.out.print(str+" ");
}
}
}
5、參考文獻:
《Java程式設計思想(美)Bruce Eckel著 陳昊鵬 譯 第4版》