用流收集數(shù)據(jù)

歸約和總結(jié)

// 菜單里有多少道菜
menu.stream().count();

// 熱量最高的菜
Comparator<Dish> calComparator = Comparator.comparingInt(Dish::getCalories);
menu.stream().collect(maxBy(calComparator));

// 匯總
menu.stream().collect(summingInt(Dish::getCalories));
// 平均數(shù)
menu.stream().collect(averagingInt(Dish::getCalories));

// 連接字符串
String s = menu.stream().map(Dish::getName).collect(joining(","));

// 廣義上的歸約總結(jié)
// 3個(gè)參數(shù)版本: 初始值、轉(zhuǎn)換函數(shù)、歸約函數(shù)
menu.stream().collect(reducing(0, Dish::getCalories, (i, j) -> i + j));
// 1個(gè)參數(shù)版本
menu.stream().collect(reducing((d1, d2) -> d1.getCalories() > d2.getCalories() ? d1 : d2));

分組

// 按菜的熱量分類
Map<CaloricLevel, List<Dish>> dishByType = menu.stream().collect(groupingBy(dish -> {
  if (dish.getCalories() <= 400) return CaloricLevel.DIET;
  else return CaloricLevel.FAT;
}));

// 先按類型再按熱量分類
Map<Dish.Type, Map<CaloricLevel, List<Dish>>> dishesByTypeCaloric = 
  groupingBy(Dish::getType,
    groupingBy( dish - > {
      if (dish.getCalories() <= 400) return CaloricLevel.DIET;
      else return CaloricLevel.FAT;
  })));

// 轉(zhuǎn)換收集器的結(jié)果類型
Map<Dish.Type, Dish> maxCaloricByType = 
  menu.stream().collect(groupingBy(Dish::getType,
    // //轉(zhuǎn)換函數(shù)collectingAndThen,接受2個(gè)參數(shù),要轉(zhuǎn)換的收集器maxBy,和轉(zhuǎn)換函數(shù)Optional::get
    collectingAndThen(maxBy(comparingInt(Dish::getCalories)), 
      Optional::get)); 

// 組合2個(gè)收集器
Map<Dish.Type, Dish> maxCaloricByType = 
  menu.stream().collect(groupingBy(Dish::getType, 
    // mapping方法接受2個(gè)參數(shù):一個(gè)是對流中元素做變化的函數(shù),另一個(gè)是收集器負(fù)責(zé)收集函數(shù)結(jié)果
    mapping( dish -> {if ...else }, toSet()
)));

分區(qū)

// 分區(qū)是分組的特殊情況,返回boolean值的分組就是分區(qū)
// 例如對素食和非素食按類型分組,得到二級Map
Map<Boolean, Map<Dish.Type, List<Dish>>> vegetarianDishesByType =
  menu.stream().collect(
    partitioningBy(Dish::isVegetarian,
      groupingBy(Dish::getType)));

收集器接口

// T是流的泛型,A是累加器的類型,R是收集操作得到的對象類型
public interface Collector<T, A, R> {
  // 建立一個(gè)新的結(jié)果容器
  Supplier<A> supplier();
  // 例如:
  public Supplier<List<T>> supplier() {
    return ArrayList::new;
  }  

  // 將元素添加到結(jié)果容器
  BiConsumer<A, T> accumulator();
  // 例如:
  public BiConsumer<List<T>, T> accumulator() {
    return (list, item) -> list.add(item);
  }
  
  // 對結(jié)果容器應(yīng)用最終轉(zhuǎn)換
  Function<A, R> finisher();
  // 例如:
  public Function<List<T>, List<T>> finisher() {
    return Function.identity();
  }

  // 合并兩個(gè)結(jié)果容器
  BinaryOperator<A> combiner();
  // 例如:
  public BinaryOperator<List<T>> combiner() {
    return (list1, list2) -> {
      list1.addAll(list2);
      return list1;
    }
  }  
  
  // 返回枚舉集合:UNORDERED, CONCURRENT, IDENTITY_FINISH
  Set<Characteristics> characteristics();
}

可以不用實(shí)現(xiàn)Collector進(jìn)行自定義收集

menuStream.collect(ArrayList::new, List::add, List::addAll);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 收集器簡介 Collector 函數(shù)式編程相對于指令式編程的一個(gè)主要優(yōu)勢:你只需要指出希望的結(jié)果“做什么”,而不用...
    潯它芉咟渡閱讀 834評論 0 4
  • 收集器簡介 匯總 并行流 歡迎訪問本人博客查看原文:http://wangnan.tech 收集器簡介 對流調(diào)用c...
    GhostStories閱讀 1,488評論 1 7
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,991評論 19 139
  • Java8 in action 沒有共享的可變數(shù)據(jù),將方法和函數(shù)即代碼傳遞給其他方法的能力就是我們平常所說的函數(shù)式...
    鐵牛很鐵閱讀 1,274評論 1 2