用流收集数据
使用groupingBy分组、以及max、min、sum
- public void printlnTest(){
- /**
- * 函数式编程相对于指令式编程的一个主要优势:你只需指出希望的
- * 结果——“做什么”,而不用操心执行的步骤——“如何做”。
- */
- ArrayList
userList = Lists.newArrayList(); - userList.add(User.builder().sex("女").name("小红").build());
- userList.add(User.builder().sex("女").name("小花").build());
- userList.add(User.builder().sex("男").name("小张").build());
- userList.add(User.builder().sex("男").name("小网").build());
- userList.add(User.builder().sex("男").name("小里").build());
-
- // 使用 groupingBy() 按男女性别分组
- Map
> sexGroup = userList.stream().collect(groupingBy(User::getSex)); - // 打印: sexGroup ==>
- // {女=[User(name=小红, sex=女, ...),User(name=小花, sex=女, ...)],
- // 男=[User(name=小张,sex=男, ...),User(name=小网, sex=男, ...),User(name=小里, sex=男, ...)]}
- System.out.println("sexGroup ==> " + sexGroup);
-
- // 统计分组的个数
- Map
groupCount = userList.stream().collect(groupingBy(User::getSex, counting())); - // groupCount ==> {女=2, 男=3}
- System.out.println("groupCount ==> " + groupCount.toString());
-
- /**
- * Collectors实用类提供了很多静态工厂方法,
- * 可以方便地创建常见收集器的实例,只要拿来用就可以了。最直接和最常用的收集器是toList
- * 静态方法,它会把流中所有的元素收集到一个List中:
- */
- List
users = userList.stream().collect(Collectors.toList()); -
- /**
- * Collectors
- * 类提供的工厂方法(例如groupingBy)创建的收集器。它们主要提供了三大功能:
- * 将流元素归约和汇总为一个值
- * 元素分组
- * 元素分区
- * 我们先来看看可以进行归约和汇总的收集器。
- */
- // 利用counting工厂方法返回的收集器,看有几个人
- // counting收集器在和其他收集器联合使用的时候特别有用,后面会谈到这一点
- long peopleCount = userList.stream().collect(Collectors.counting());
- // 或者 userList.stream().count(); userList.size();
-
- // Java Stream Collectors的maxBy() minBy()、groupingBy()、partitioningBy()的使用
- // userList.stream().map(user -> user.getUId()).collect(Collectors.maxBy(Comparator.naturalOrder()));
- Optional
comparatorMax = userList.stream().map(User::getUId).max(Comparator.naturalOrder()); - System.out.println("stream() comparatorMax :" + comparatorMax.orElse(0));
-
- // minBy()
- Optional
comparatorMin = userList.stream().map(User::getUId).min(Comparator.naturalOrder()); - System.out.println("stream() comparatorMin :" + comparatorMax.orElse(0));
-
- // summingInt 求和
- // userList.stream().collect(summingInt(User::getUId))
- int summingInt = userList.stream().mapToInt(User::getUId).sum();
- }
对groupingBy的理解图:
- Map
Integer> totalCaloriesByType = menu.stream() - .collect(groupingBy(Dish::getType,summingInt(Dish::getCalories)));
- Map
> caloricLevelsByType = - menu.stream().collect(groupingBy(Dish::getType,
- mapping(dish -> { if (dish.getCalories() <= 400)
- return CaloricLevel.DIET;
- else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
- else return CaloricLevel.FAT; },
- toSet() )));
使用partitioningBy、collectingAndThen
- public void demo(){
- ArrayList
userList = Lists.newArrayList(); - userList.add(User.builder().sex("女").name("小红").type(true).uId(10).build());
- userList.add(User.builder().sex("女").name("小花").type(false).uId(11).build());
- userList.add(User.builder().sex("男").name("小张").type(true).uId(12).build());
- userList.add(User.builder().sex("男").name("小网").type(false).uId(13).build());
- userList.add(User.builder().sex("男").name("小里").type(true).uId(14).build());
-
- /**
- * 先根据类型分组、再根据性别分组
- */
- Map
>> collect = userList.stream().collect(partitioningBy(User::isType, groupingBy(User::getSex))); - // {false={
- // 女=[
- // User(uId=null, name=小花, email=null, sex=女, type=false)
- // ],
- // 男=[
- // User(uId=null, name=小网, email=null, sex=男, type=false)
- // ]},
- //
- // true={
- // 女=[
- // User(uId=null, name=小红, email=null, sex=女, type=true)
- // ],
- // 男=[
- // User(uId=null, name=小张, email=null, sex=男, type=true),
- // User(uId=null, name=小里, email=null, sex=男, type=true)
- // ]}
- // }
- System.out.println(collect.toString());
-
- // 查询true和false中两个类型中,uid最大的对象
- Map
collectType = userList.stream().collect(partitioningBy(User::isType, collectingAndThen(maxBy(comparingInt(User::getUId)), Optional::get))); - // {
- // false = User(uId=13, name=小网, sex=男, type=false),
- // true = User(uId=14, name=小里, sex=男, type=true)
- // }
- System.out.println(collectType.toString());
-
- }
Collector收集器的介绍及使用
一个Collector收集器由四个函数指定,这四个函数一起工作以将条目累积到可变结果容器中,并可选择对结果执行最终转换。他们是:
收集器还具有一组特征,例如Collector.Characteristics.CONCURRENT,提供了可以缩减实现使用,以提供更好性能的提示。
使用收集器缩减的顺序实现将使用supplier函数创建单个结果容器,并为每个输入元素调用一次accumulator累加器函数。并行实现将对输入进行分区,为每个分区创建一个结果容器,将每个分区的内容累积到该分区的子结果中,然后使用combiner组合器函数将子结果合并为组合结果。为确保顺序和并行执行产生相同的结果,收集器函数必须满足标识和关联约束。