Iterable 接口解析

Iterable<T> 接口解析

一、說明

源碼中對 Iterable 的說明是這樣的:Implementing this interface allows an object to be the target of the “for-each loop” statement. See For-each Loop(實現此接口允許對象成爲“ for-each循環”語句的目標。 請參閱 《For-each Loop》

意思就是說:實現此接口的類可以使用增強 for 循環。簡單的例子如下:

// 增強 for 循環代碼
private static final void descForeachLoop() {
    List<Integer> list = Arrays.asList(1,2,3,4);
    for (Integer i : list) {
        System.out.println(i);
    }
}

// Java 會自動編譯成如下代碼
private static final void descForeachLoop() {
    List<Integer> list = Arrays.asList(1, 2, 3, 4);
    Iterator var1 = list.iterator();

    while(var1.hasNext()) {
        Integer i = (Integer)var1.next();
        System.out.println(i);
    }

}

具體的解釋可以參考 《For-each Loop》

二、源碼

public interface Iterable<T> {
    Iterator<T> iterator();
    default void forEach(Consumer<? super T> action) {...}
    default Spliterator<T> spliterator() {...}
}

三、方法解析

關於泛型的說明大家可以參考 《Java知識點總結(Java泛型)》 ,或者自行搜索,這邊不做過多的說明。

iterator() 方法

該方法沒有參數,返回一個能夠遍歷容器的迭代器 Iterator<T> 。

迭代及的作用就是對容器中的元素進行遍歷。具體的 Iterator 解析會在後續的文章中進行分析(TODO Iterator<T> 源碼解析),需要的人可以自行搜索或等待後續文章。

forEach(Consumer<? super T> action)
循環容器中的元素,並對每個元素進行 action 操作,容器中不能有空元素,否則或拋出 NullPointerException 指針異常。例子:

private static final void descForeach() {
    LinkedList<String> linkedList = new LinkedList<>();
    linkedList.add("dddd");
    linkedList.add("eeee");
    linkedList.forEach(System.out::println);
}

關於例子中的 Lambda 表達式,可以參考《Java 8 實戰》 密碼:u3ex56,或者加QQ羣:247498058 索取。

spliterator()

spliterator 方法沒有參數,返回一個 Spliterator<T> 對象,Spliterator接口是1.8新加的接口,字面意思可分割的迭代器,不同以往的iterator需要順序迭代,Spliterator可以分割爲若干個小的迭代器進行並行操作,既可以實現多線程操作提高效率,又可以避免普通迭代器的fail-fast機制所帶來的異常。Spliterator可以配合1.8新加的Stream進行並行流的實現,大大提高處理效率。具體的 Spliterator 解析會在後續的文章中進行分析(TODO Spliterator<T> 源碼解析),也可以參考《java源碼品讀(9)— Spliterator》

一個小例子:

private static final void descSpliterator() {
    List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
    Spliterator<Integer> spliterator = list.spliterator();
    Spliterator<Integer> integerSpliterator = spliterator.trySplit();
    Spliterator<Integer> integerSpliterator1 = integerSpliterator.trySplit();
    spliterator.forEachRemaining(new MyConsumer<>());
    System.out.println("--------------");
    integerSpliterator.forEachRemaining(new MyConsumer<>());
    System.out.println("--------------");
    integerSpliterator1.forEachRemaining(new MyConsumer<>());
    System.out.println("--------------");

    list.stream().parallel().forEach(new MyConsumer<>());
    System.out.println("--------------");
    list.stream().forEach(new MyConsumer<>());
}

private static class MyConsumer<T> implements Consumer<T> {

    @Override
    public void accept(T o) {
        try {
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() + "--" + o.toString());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

// 執行結果如下:
main--4
main--5
main--6
main--7
--------------
main--2
main--3
--------------
main--1
--------------
main--5
ForkJoinPool.commonPool-worker-1--2
ForkJoinPool.commonPool-worker-2--7
ForkJoinPool.commonPool-worker-3--1
ForkJoinPool.commonPool-worker-3--4
ForkJoinPool.commonPool-worker-2--6
ForkJoinPool.commonPool-worker-1--3
--------------
main--1
main--2
main--3
main--4
main--5
main--6
main--7

五、總結

該說的上面都已經說過了:

  • Iterable<T> 接口提供一個增強 for 循環的實現
  • 提供一個默認 forEach 方法迭代元素
  • 對多線程,多 CPU 並行支持

六、參考資料

《For-each Loop》

《Java知識點總結(Java泛型)》

《java源碼品讀(9)— Spliterator》

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