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 並行支持