美文网首页
用流收集数据

用流收集数据

作者: 上海马超23 | 来源:发表于2017-07-15 11:02 被阅读0次

    归约和总结

    // 菜单里有多少道菜
    menu.stream().count();
    
    // 热量最高的菜
    Comparator<Dish> 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<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;
      })));
    
    // 转换收集器的结果类型
    Map<Dish.Type, Dish> maxCaloricByType = 
      menu.stream().collect(groupingBy(Dish::getType,
        // //转换函数collectingAndThen,接受2个参数,要转换的收集器maxBy,和转换函数Optional::get
        collectingAndThen(maxBy(comparingInt(Dish::getCalories)), 
          Optional::get)); 
    
    // 组合2个收集器
    Map<Dish.Type, Dish> maxCaloricByType = 
      menu.stream().collect(groupingBy(Dish::getType, 
        // mapping方法接受2个参数:一个是对流中元素做变化的函数,另一个是收集器负责收集函数结果
        mapping( dish -> {if ...else }, toSet()
    )));
    

    分区

    // 分区是分组的特殊情况,返回boolean值的分组就是分区
    // 例如对素食和非素食按类型分组,得到二级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> {
      // 建立一个新的结果容器
      Supplier<A> supplier();
      // 例如:
      public Supplier<List<T>> supplier() {
        return ArrayList::new;
      }  
    
      // 将元素添加到结果容器
      BiConsumer<A, T> accumulator();
      // 例如:
      public BiConsumer<List<T>, T> accumulator() {
        return (list, item) -> list.add(item);
      }
      
      // 对结果容器应用最终转换
      Function<A, R> finisher();
      // 例如:
      public Function<List<T>, List<T>> finisher() {
        return Function.identity();
      }
    
      // 合并两个结果容器
      BinaryOperator<A> combiner();
      // 例如:
      public BinaryOperator<List<T>> combiner() {
        return (list1, list2) -> {
          list1.addAll(list2);
          return list1;
        }
      }  
      
      // 返回枚举集合:UNORDERED, CONCURRENT, IDENTITY_FINISH
      Set<Characteristics> characteristics();
    }
    

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

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

    相关文章

      网友评论

          本文标题:用流收集数据

          本文链接:https://www.haomeiwen.com/subject/xfzohxtx.html