用流收集数据

归约和总结

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

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

// 汇总
menu.stream().collect(summingInt(Dish::getCalories));
// 平均数
menu.stream().collect(averagingInt(Dish::getCalories));

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

// 广义上的归约总结
// 3个参数版本: 初始值、转换函数、归约函数
menu.stream().collect(reducing(0, Dish::getCalories, (i, j) -> i + j));
// 1个参数版本
menu.stream().collect(reducing((d1, d2) -> d1.getCalories() > d2.getCalories() ? d1 : d2));

分组

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

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

// 转换收集器的结果类型
Map maxCaloricByType = 
  menu.stream().collect(groupingBy(Dish::getType,
    // //转换函数collectingAndThen,接受2个参数,要转换的收集器maxBy,和转换函数Optional::get
    collectingAndThen(maxBy(comparingInt(Dish::getCalories)), 
      Optional::get)); 

// 组合2个收集器
Map maxCaloricByType = 
  menu.stream().collect(groupingBy(Dish::getType, 
    // mapping方法接受2个参数:一个是对流中元素做变化的函数,另一个是收集器负责收集函数结果
    mapping( dish -> {if ...else }, toSet()
)));

分区

// 分区是分组的特殊情况,返回boolean值的分组就是分区
// 例如对素食和非素食按类型分组,得到二级Map
Map>> vegetarianDishesByType =
  menu.stream().collect(
    partitioningBy(Dish::isVegetarian,
      groupingBy(Dish::getType)));

收集器接口

// T是流的泛型,A是累加器的类型,R是收集操作得到的对象类型
public interface Collector {
  // 建立一个新的结果容器
  Supplier supplier();
  // 例如:
  public Supplier> supplier() {
    return ArrayList::new;
  }  

  // 将元素添加到结果容器
  BiConsumer accumulator();
  // 例如:
  public BiConsumer, T> accumulator() {
    return (list, item) -> list.add(item);
  }
  
  // 对结果容器应用最终转换
  Function finisher();
  // 例如:
  public Function, List> finisher() {
    return Function.identity();
  }

  // 合并两个结果容器
  BinaryOperator combiner();
  // 例如:
  public BinaryOperator> combiner() {
    return (list1, list2) -> {
      list1.addAll(list2);
      return list1;
    }
  }  
  
  // 返回枚举集合:UNORDERED, CONCURRENT, IDENTITY_FINISH
  Set characteristics();
}

可以不用实现Collector进行自定义收集

menuStream.collect(ArrayList::new, List::add, List::addAll);

你可能感兴趣的:(用流收集数据)