int sum = employees.stream() .filter(employee ->employee.getGender() == Gender2.MALE) .mapToInt(Employee2::getAge) .reduce((total,age) -> total + age) .getAsInt();該書還有句話是這麼說的,若是reduce()沒有指定初值,就會試著使用該組數據中第一個元素作為第一次呼叫Lambda表示式時的第一個引數值。
老實說我第一次看到就想說這樣第一的值不是被重複計算了嗎?
(第一個引數是上次運算結果,第二個引數是目前走訪的元素)
所以查了一下API文件發現,reduce()的作用大概同等於(但不限制為按順序執行。):
boolean foundAny = false; T result = null; for (T element : this stream) { if (!foundAny) { foundAny = true; result = element; } else result = accumulator.apply(result, element); } return foundAny ? Optional.of(result) : Optional.empty();所以大概可以想成 第一個引數直接指定成該組數據中的第一個元素吧! (如果有的話)。
我寫了一個測試程式發現 迭代的第一次確實沒有進去執行reduce中的lambda表示式。
(或許應該說第一次執行時就將該組數據中第一個元素當成lambda表示式的第一個引數,第二個元素當成lambda表示式的第二個引數。)
package learning.test; import java.util.Arrays; import java.util.List; public class StreamTest { public static void main(String[] args) { List<Employee> employees = Arrays.asList(new Employee(10), new Employee(20), new Employee(30), new Employee(50)); int sum = employees.stream().filter(employee -> employee.getAge() > 10) .mapToInt(Employee::getAge).reduce((total, age) -> { System.out.println("age=" + age); System.out.println("total=" + total); System.out.println("-----------"); return total + age; }).getAsInt(); System.out.println(sum); } } class Employee { int age; Employee(int a) { age = a; } public int getAge() { return age; } }輸出結果:
age=30 total=20 ----------- age=50 total=50 ----------- 100
沒有留言:
張貼留言