深入 java8 第 07 篇 ( Stream API 的操作->规约,收集 )
一、Stream API 的操作步骤:
创建 Stream
中间操作
终止操作(终端操作 -> 规约,收集)
7.1 规约
reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。 返回 T
reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。 返回 Optional<T>
7.1.1 准备测试数据
List<Employee> emps = Arrays.asList(
new Employee(001, "Emma", 41, 20000, Status.FREE),
new Employee(002, "Mary", 39, 18000, Status.BUSY),
new Employee(003, "Allen", 33, 15000, Status.BUSY),
new Employee(004, "Olivia", 52, 32000, Status.FREE),
new Employee(005, "Natasha", 27, 13000, Status.BUSY),
new Employee(006, "Kevin", 25, 10000, Status.FREE),
new Employee(007, "Haivent", 25, 12000, Status.FREE)
);
List<Integer> numList = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
7.1.2 测试规约
@Test
public void test01(){
// 所有整数累加和
Integer reduce = numList.stream()
.reduce(0, (x,y)->x+y); System.out.println(reduce); // 所有薪资累加和 Optional<Double> reduce2 = emps.stream() .map(Employee::getSalary) .reduce(Double::sum); System.out.println("\n"+reduce2.get()); }
7.1.3 需求:统计所有姓名中 “A” 的出现次数
@Test
public void test02(){
Optional<Integer> reduce = emps.stream()
.map(Employee::getName)
.flatMap(StreamAPI03::filterCharacter)
.map((e)->{ if(e.equals('A')){ return 1; }else{ return 0; } }) .reduce(Integer::sum); System.out.println(reduce.get()); } private static Stream<Character> filterCharacter(String str){ List<Character> list = new ArrayList<>(); for (Character ch : str.toCharArray()) { list.add(ch); } return list.stream(); }
7.2 收集
collect(Collector c) 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法。
Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、 Set、 Map)。但是 Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例, 具体方法与实例如下:
方法与实例:
toList
List<T> 把流中元素收集到List
toSet
Set<T> 把流中元素收集到Set
toCollection
Collection<T> 把流中元素收集到创建的集合
counting
Long 计算流中元素的个数
summingInt
Integer 对流中元素的整数属性求和
averagingInt
Double 计算流中元素Integer属性的平均值
summarizingInt
IntSummaryStatistics 收集流中Integer属性的统计值。如:平均值
joining
String 连接流中每个字符串
maxBy
Optional<T> 根据比较器选择最大值
minBy
Optional<T> 根据比较器选择最小值
reducing
归约产生的类型 从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值
collectingAndThen
转换函数返回的类型 包裹另一个收集器,对其结果转换函数
groupingBy
Map<K, List<T>> 根据某属性值对流分组,属性为K,结果为V
partitioningBy
Map<Boolean, List<T>> 根据true或false进行分区
7.2.1 测试收集 收集到集合
@Test
public void test03(){
List<String> collect = emps.stream()
.map(Employee::getName)
.collect(Collectors.toList());
collect.forEach(System.out::println);
System.out.println();
Set<String> collect2 = emps.stream()
.map(Employee::getName)
.collect(Collectors.toSet());
collect2.forEach(System.out::println);
System.out.println();
ArrayList<String> collect3 = emps.stream()
.map(Employee::getName)
.collect(Collectors.toCollection(ArrayList::new));
collect3.forEach(System.out::println);
}
7.2.3 对流中元素进行计算
@Test
public void test04(){
Long collect = emps.stream()
.collect(Collectors.counting());
System.out.println("总员工数:"+collect);
Double collect2 = emps.stream()
.collect(Collectors.summingDouble(Employee::getSalary));
System.out.println("\n每月应发薪资总额:"+collect2);
Double collect3 = emps.stream()
.collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println("\n员工平均月薪:"+collect3);
DoubleSummaryStatistics collect4 = emps.stream()
.collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println("\n员工中最低薪资为:"+collect4.getMin());
Optional<Double> collect5 = emps.stream()
.map(Employee::getSalary)
.collect(Collectors.maxBy(Double::compare));
System.out.println("\n员工中薪资最高为:"+collect5.get());
Optional<Double> collect6 = emps.stream()
.map(Employee::getSalary)
.collect(Collectors.minBy(Double::compare));
System.out.println("\n员工中薪资最低为:"+collect6.get());
Optional<Double> collect7 = emps.stream()
.map(Employee::getSalary)
.collect(Collectors.reducing(Double::sum));
System.out.println("\n员工每月薪资总共为:"+collect7.get());
}
7.2.4 将多个字符串连接成一个字符串
@Test
public void test05(){
String collect = emps.stream()
.map(Employee::getName)
.collect(Collectors.joining("-"));
System.out.println(collect);
}
7.2.5 对类型转换为集合后,返回集合大小
@Test
public void test06(){
Integer collect = emps.stream()
.collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
System.out.println(collect);
}
7.2.6 单级分组
@Test
public void test07(){
Map<Status, List<Employee>> collect = emps.stream()
.collect(Collectors.groupingBy(Employee::getStatus));
System.out.println(collect);
}
7.2.7 多级分组
@Test
public void test08(){
Map<String, Map<String, List<Employee>>> collect = emps.stream()
.collect(Collectors.groupingBy((e)->{ if(e.getStatus() == Status.FREE){ return "空闲"; }else{ return "繁忙"; } }, Collectors.groupingBy((e)->{ if(e.getSalary() > 10000){ return "大于 15000"; }else if (e.getSalary() > 20000){ return "大于 20000"; }else{ return "大于25000"; } }))); System.out.println(collect); }
根据员工状态进行分区
@Test
public void test09(){
Map<Boolean, List<Employee>> collect = emps.stream()
.collect(Collectors.partitioningBy((e)->e.getStatus() == Status.FREE)); System.out.println(collect); }
源码下载地址:https://download.csdn.net/download/hello_world_qwp/10401249