我覺得你可能真的還不會Java

千鋒Python唐小強發表於2020-07-01

Stream API為我們提供了Stream.reduce用來實現集合元素的歸約。reduce函式有三個引數:

  • Identity標識:一個元素,它是歸約操作的初始值,如果流為空,則為預設結果。
  • Accumulator累加器:具有兩個引數的函式:歸約運算的部分結果和流的下一個元素。
  • Combiner合併器(可選):當歸約並行化時,或當累加器引數的型別與累加器實現的型別不匹配時,用於合併歸約操作的部分結果的函式。
    注意觀察上面的圖,我們先來理解累加器:
  • 階段累加結果作為累加器的第一個引數
  • 集合遍歷元素作為累加器的第二個引數

Integer型別歸約

reduce初始值為0,累加器可以是lambda表示式,也可以是方法引用。


List<Integer> 
numbers 
= 
Arrays.asList(1, 
2
, 
3
, 
4
, 
5
, 
6
);

int result = numbers
        .stream()
        .reduce(0, (subtotal, element) -> subtotal + element);
System.out.println(result);   //21

int result = numbers
        .stream()
        .reduce(0, Integer::sum);
System.out.println(result); //21

String型別歸約

不僅可以歸約Integer型別,只要累加器引數型別能夠匹配,可以對任何型別的集合進行歸約計算。

List<String> letters = Arrays.asList(
"a", 
"b", 
"c", 
"d", 
"e");

String result = letters
       .stream()
       .reduce( "", (partialString, element) -> partialString + element);
System.out.println(result);   //abcde


String result = letters
       .stream()
       .reduce( "", String::concat);
System.out.println(result);   //ancde

複雜物件歸約

計算所有的員工的年齡總和。

Employee e1 = 
new Employee(
1,
23,
"M",
"Rick",
"Beethovan");

Employee e2 = new Employee( 2, 13, "F", "Martina", "Hengis");
Employee e3 = new Employee( 3, 43, "M", "Ricky", "Martin");
Employee e4 = new Employee( 4, 26, "M", "Jon", "Lowman");
Employee e5 = new Employee( 5, 19, "F", "Cristine", "Maria");
Employee e6 = new Employee( 6, 15, "M", "David", "Feezor");
Employee e7 = new Employee( 7, 68, "F", "Melissa", "Roy");
Employee e8 = new Employee( 8, 79, "M", "Alex", "Gussin");
Employee e9 = new Employee( 9, 15, "F", "Neetu", "Singh");
Employee e10 = new Employee( 10, 45, "M", "Naveen", "Jain");


List<Employee> employees = Arrays.asList(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);


Integer total = employees.stream().map(Employee::getAge).reduce( 0,Integer::sum);
System.out.println(total); //346
  • 先用map將Stream流中的元素由Employee型別處理為Integer型別(age)。
  • 然後對Stream流中的Integer型別進行歸約

Combiner合併器的使用

除了使用map函式實現型別轉換後的集合歸約,我們還可以用Combiner合併器來實現,這裡第一次使用到了Combiner合併器。因為Stream流中的元素是Employee,累加器的返回值是Integer,所以二者的型別不匹配。這種情況下可以使用Combiner合併器對累加器的結果進行二次歸約,相當於做了型別轉換。

Integer total3 = employees.stream()

       .reduce( 0, (totalAge,emp) -> totalAge + emp.getAge(),Integer::sum); //注意這裡reduce方法有三個引數
System.out.println(total); // 346

計算結果和使用map進行資料型別轉換的方式是一樣的。

並行流資料歸約(使用合併器)

對於大資料量的集合元素歸約計算,更能體現出Stream並行流計算的威力。

我覺得你可能真的還不會Java

在進行並行流計算的時候,可能會將集合元素分成多個組計算。為了更快的將分組計算結果累加,可以使用合併器。

Integer total2 = employees

       .parallelStream()
       .map(Employee::getAge)
       .reduce( 0,Integer::sum,Integer::sum);   //注意這裡reduce方法有三個引數

System.out.println(total); // 346


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69923331/viewspace-2701681/,如需轉載,請註明出處,否則將追究法律責任。

相關文章