08. Java8-流式API-终端操作collect

x33g5p2x  于2021-12-18 转载在 其他  
字(5.9k)|赞(0)|评价(0)|浏览(294)

集合的stream()方法是将集合转换为流形式以处理数据, Stream的collect 是将流转换为集合或其它形式存储流运算结果. Collector 接口中方法的实现决定了如何对流执行收集操作,但并非一定要自己去实现此接口, Collectors 实现类提供了很多静态方法, 可以便捷地创建收集器实例.

1. 常用收集器

测试数据如下:

static List<Employee> emps = new ArrayList<>();

static {

    emps.add(new Employee(1001, "张三", "Man", 50));
    emps.add(new Employee(1002, "李四", "Man", 30));
    emps.add(new Employee(1003, "王五", "Woman", 25));
    emps.add(new Employee(1004, "赵六", "Man", 35));
    emps.add(new Employee(1005, "小七", "Woman", 30));
    emps.add(new Employee(1006, "周八", "Man", 42));
}

1.1 toList

将流元素收集到ArrayList 中.

// 将处理后的流中所有元素收集到list中,list 为 java.util.ArrayList
@Test
public void test_toList(){

    List<String> list = emps.stream()
            .filter((employee -> "Woman".equals(employee.getSex())))
            .map((employee -> employee.getName()))
            .collect(Collectors.toList());

    list.forEach(System.out::println);
    System.out.println(list.getClass());
}

1.2 toSet

将流元素收集到HashSet 中

// 将处理后的流中所有元素收集到Set 中, Set为 java.util.HashSet
@Test
public void test_toSet(){
    Set<String> set = emps.stream()
            .filter((employee -> "Man".equals(employee.getSex())))
            .map((employee -> employee.getName()))
            .collect(Collectors.toSet());

    set.forEach(System.out::println);
    System.out.println(set.getClass());
}

1.3 toCollection

将流元素收集到自定义容器中

// 自定义集合数据结构
@Test
public void test_toCollection(){
    Set<String> set = emps.stream()
            .filter((employee -> "Man".equals(employee.getSex())))
            .map((employee -> employee.getName()))
            .collect(Collectors.toCollection(LinkedHashSet::new));

    System.out.println(set.getClass());

}

1.4 counting

计算流中元素个数

//获取流中元素总数量
@Test
public void test_counting(){
    Long total = emps.stream().collect(Collectors.counting());
    System.out.println("流中元素总数量: " + total);
}

1.5 aggregation

聚合操作, 包含: counting(), maxBy(), minBy(), summingInt(), averagingInt(), summingLong(), averagingLong(), summingDouble(), averagingDouble() 等API

// 测试聚合函数
@Test
public void test_aggregation(){
    Long count = emps.stream().collect(Collectors.counting());
    Integer sum = emps.stream().collect(Collectors.summingInt(Employee::getAge));
    Double average = emps.stream().collect(Collectors.averagingInt(Employee::getAge));
    Optional<Employee> maxOp = emps.stream().collect(Collectors.maxBy((e1, e2) -> e1.getAge().compareTo(e2.getAge())));
    Optional<Employee> minOp = emps.stream().collect(Collectors.minBy((e1, e2) -> e1.getAge().compareTo(e2.getAge())));

    System.out.println("员工列表中男性总数量: " + count);
    System.out.println("员工列表中男性总年龄: " + sum);
    System.out.println("员工列表中男性平均年龄: " + average);
    System.out.println("员工列表中男性最大年龄: " + maxOp.get());
    System.out.println("员工列表中平均年龄: " + minOp.get());
}
// 对Int类型做聚合运算,形似API 还有summarizingDouble, summarizingLong
@Test
public void test_summarizingInt(){
    // 对于自定义对象流,可使用collect 获取*statistics 聚合函数信息, 对于特定流 Int/Double/LongStream, 提供了对应的方法
    IntSummaryStatistics statistics = emps.stream()
            .filter((employee -> "Man".equals(employee.getSex())))
            .collect(Collectors.summarizingInt(Employee::getAge));

    System.out.println("员工列表中男性总数量: " + statistics.getCount());
    System.out.println("员工列表中男性总年龄: " + statistics.getSum());
    System.out.println("员工列表中男性平均年龄: " + statistics.getAverage());
    System.out.println("员工列表中男性最大年龄: " + statistics.getMax());
    System.out.println("员工列表中平均年龄: " + statistics.getMin());

    DoubleSummaryStatistics dbStatistics = DoubleStream.of(10.0, 15.5, 20.5, 31.5, 40.0).summaryStatistics();
    System.out.println("流中元素总数量:" + dbStatistics.getCount());
    System.out.println("流中元素总和:" + dbStatistics.getSum());
    System.out.println("流中元素平均值:" + dbStatistics.getAverage());
    System.out.println("流中元素最大值:" + dbStatistics.getMax());
    System.out.println("流中元素最小值:" + dbStatistics.getMin());

}

1.6 groupingBy

将流中元素进行分组

// 分组函数: 可进行一级或多级分组, 返回为map 结构
@Test
public void test_groupingBy(){

    // 一级分组: 按性别分组
    Map<String, List<Employee>> sexMap = emps.stream().collect(Collectors.groupingBy(Employee::getSex));

    // 而二级分组: 先按性别分组, 再按年龄分组
    Map<String, Map<String, List<Employee>>> map = emps.stream()
            .collect(Collectors.groupingBy(Employee::getSex,
                    Collectors.groupingBy((employee) -> {
                        if (employee.getAge() < 20) {
                            return "青年";
                        } else if (employee.getAge() < 40) {
                            return "中年";
                        } else {
                            return "老年";
                        }
                    })));

    System.out.println(sexMap);
    System.out.println(map);
}

1.7 partitional

将流中元素进行分区.

// 分区,按照是否满足条件分为两组, 可嵌套分组
@Test
public void test_partitional(){
    // 一级分组
    Map<Boolean, List<Employee>> map1 = emps.stream()
            .collect(Collectors.partitioningBy((employee) -> employee.getAge() > 30));
    System.out.println("年龄大于30岁的: " + map1.get(true));
    System.out.println("年龄小于30岁的: " + map1.get(false));

    System.out.println("----------------------------------------------------------------------------------");

    // 多机分组
    Map<Boolean, Map<Boolean, List<Employee>>> map2 = emps.stream()
            .collect(Collectors.partitioningBy((employee) -> employee.getAge() > 30,
                    Collectors.partitioningBy((employee) -> "Man".equals(employee.getSex()))));

    System.out.println("年龄大于30岁的男性: " + map2.get(true).get(true));
    System.out.println("年龄大于30岁的女性: " + map2.get(true).get(false));
    System.out.println("年龄小于30岁的男性: " + map2.get(false).get(true));
    System.out.println("年龄小于30岁的女性: " + map2.get(false).get(false));

}

1.8 join

对流中元素进行字符串拼接.

// 拼接字符串
@Test
public void test_join(){

    String names = emps.stream()
            .map((employee -> employee.getName()))
            .collect(Collectors.joining(",", "(", ")"));

    System.out.println(names);

}

1.9 reducing

对流中元素做迭代式运算.

// reducing 对流中元素做聚合运算, 类似于stream.reduce()
@Test
public void test_reducing(){

    Integer sum = emps.stream().collect(Collectors.reducing(0, Employee::getAge, Integer::sum));
    System.out.println(sum);
}

1.10 collectingAndThen

包裹另外一个收集器, 对其结果做转换函数.

// 包含另外一个收集器
@Test
public void test_collectingAndThen(){
    Integer size = emps.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
    System.out.println(size);
}

相关文章