java8新特性[2]:內部迭代和外部迭代(Internal vs external iteration)
Java8 增加了新的語言特性(例如 lambda 表示式和預設方法),為此 Java8 的類庫也進行了很多改進,例如從外部迭代到內部迭代的改變。
集合類庫主要依賴於外部迭代(external iteration)。Collection 實現 Iterable 介面,從而使得使用者可以依次遍歷集合的元素。比如我們需要把一個集合中的形狀都設定成紅色,那麼可以這麼寫:
1 2 3 |
for (Shape shape : shapes) { shape.setColor(RED); } |
這個例子演示了外部迭代:for-each 迴圈呼叫 shapes 的 iterator() 方法進行依次遍歷。外部迴圈的程式碼非常直接,但它有如下問題:
(1)Java 的 for 迴圈是序列的,而且必須按照集合中元素的順序進行依次處理;
(2)集合框架無法對控制流進行優化,例如通過排序、並行、短路(short-circuiting)求值以及惰性求值改善效能。
儘管有時 for-each 迴圈的這些特性(序列,依次)是我們所期待的,但它對改善效能造成了阻礙。實際上,我們可以使用內部迭代(internal iteration)替代外部迭代,使用者把對迭代的控制權交給類庫,並向類庫傳遞迭代時所需執行的程式碼。下面是前例的內部迭代程式碼:
1 |
shapes.forEach(s -> s.setColor(RED)); |
儘管看起來只是一個小小的語法改動,但是它們的實際差別非常巨大。使用者把對操作的控制權交還給類庫,從而允許類庫進行各種各樣的優化(例如亂序執行、惰性求值和並行等等)。總的來說,內部迭代使得外部迭代中不可能實現的優化成為可能。
如上所示:外部迭代同時承擔了做什麼(把形狀設為紅色)和怎麼做(得到 Iterator 例項然後依次遍歷)兩項職責,而內部迭代只負責做什麼,而把怎麼做留給類庫。通過這樣的職責發生了轉變:使用者的程式碼會變得更加清晰,而類庫則可以進行各種優化,從而使所有使用者都從中受益。