理解java Foreach

1,定義容器能夠foreach遍歷
2.分析使用Arraylist foreach遍歷時移除數據異常

java容器都具有用於遍歷數據的foreach功能,如果自己定義一個容器類,如何實現這個語法呢?

第一步:實現Iterable接口

實現接口就要實現內部的方法(java8 default修飾的方法無需實現)

public class ForEachClass<T> implements Iterable<T> {
    @Override
    public Iterator iterator() {
        return null;
    }
}

第二步:實現接口方法

因爲接口返回iterator對象,所以需要iterator是一個接口,所以必須定義一個實現iterator接口的類,然後實例化後成爲對象再返回.

public class TestForEach {

    //注1:T泛型作爲該自定義容器數據的類型
    static class ForEachClass<T> implements Iterable<T> {
        Object[] value = null;
        int current = 0;
        //用於測試
        public void addvalue(T... t) {
            value = t;
        }
        //注2:每次foreach都會調用該方法
        @Override
        public Iterator<T> iterator() {
            current = 0;
            //參考list,用到是new,所以應該沒問題
            return new It();
        }

注1:這裏Iterable的泛型就是foreach中遍歷數據所對應的類型.
注2:實現Iterable接口

Iterator是一個接口,需要自定義Iterator實現類,實現其hasNext和next方法

        private class It implements Iterator<T> {
            //注3:是否存在下一個元素,foreach停止的判斷條件
            @Override
            public boolean hasNext() {
                return value != null && current < value.length;
            }
            //注4:返回一下一個元素,作爲foreach輸出
            @Override
            public T next() {
                T t = (T) value[current];
                current++;
                return t;
            }
        }
    }
}

注3:是否存在下一個元素,foreach停止的判斷條件
注4:返回一下一個元素,作爲foreach輸出

foreach遍歷

        ForEachClass<Integer test = new ForEachClass();
        test.addvalue(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        for (Integer a : test) {//測試
            System.out.print(a + " ");
        }

迭代器遍歷數據

當這個容器類可以通過foreach遍歷數據後,這個類也能通過迭代器遍歷數據

        Iterator iterator =test.iterator();//注1,上步實現的接口
        while(iterator.hasNext()){//注2:上步實現iterator接口的hasNext
            Intenger i = iterator.next();//注3:上步實現iterator接口的next
            }
        }

注1,上步實現的接口
注2:上步實現iterator接口的hasNext
注3:上步實現iterator接口的next
上面3個方法均在實現foreach的時候實現了

foreach中刪除數據報錯

在list中,remove一個數據會導致foreach報ConcurrentModificationException異常
因爲foreach會調用迭代器中next方法,next方法會調用checkForComodification,

public E next() {
       checkForComodification(); 
       ....
}
final void checkForComodification() {
if (modCount != expectedModCount)
       throw new ConcurrentModificationException();
}

因爲list在remove和add的時候會改變modCount的值,expectedModCount只會在foeach開始賦值,在foreach每次調用next都會比較這兩個值,看是否相等,如果不等就報錯.估計設計這個的工程師只想讓foreach只能作爲遍歷數據使用,防止出現其他的bug,畢竟foreach的細節不可見.如果要在遍歷過程中刪除和數據,可以使用迭代器.如下;

        Iterator iterator =test.iterator();
        while(iterator.hasNext()){
            if (iterator.next().equals("3")){
                iterator.remove();
            }
        }

除了容器類可以使用foreach遍歷數據,數組也能通過這種方式遍歷,如:

String[] arg =new String[10];
for(String s:arg) {
///XXXX
}

數組結構比較簡單,而且沒有方法,只有通過length知道大小,通過下標訪問和寫入,編譯器就很輕鬆處理數組的foreach語法.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章