美文网首页
Java8 Stream 之分组与分区

Java8 Stream 之分组与分区

作者: Tinyspot | 来源:发表于2023-11-10 09:43 被阅读0次

    1. 分组 groupingBy()

    • Function 是分类函数,可以把流中的元素分成不同的组
    • 分组操作的结果是一个Map,把分组函数返回的值作为映射的键,把流中所有具有这个分类值的项目的列表作为对应的映射值
    • 键:分类值,值:包含分类值的列表

    1.2 分组操作

    • Collector.groupingBy(Function classifier)
    @Test
    public void group() {
        List<OrderDTO> orderDTOS = Arrays.asList(new OrderDTO("1001", "20230101", 0, 30L),
                new OrderDTO("1002", "20230102", -1, 100L),
                new OrderDTO("1003", "20230103", 0, 50L));
    
        // 按 orderStatus 分组
        Map<Integer, List<OrderDTO>> orderStatusMap = orderDTOS.stream().collect(
                Collectors.groupingBy(OrderDTO::getOrderStatus));
    
        Map<Boolean, List<OrderDTO>> booleanMap = orderDTOS.stream().collect(
                groupingBy(orderDO -> orderDO.getOrderAmount() > 50));
    }
    
    @Data
    public class OrderDTO implements Serializable {
        private static final long serialVersionUID = 177087236253361067L;
    
        private String orderCode;
        private String tradeId;
        private Integer orderStatus;
        private Long orderAmount;
    
        public OrderDTO(String orderCode, String tradeId, Integer orderStatus, Long orderAmount) {
            this.orderCode = orderCode;
            this.tradeId = tradeId;
            this.orderStatus = orderStatus;
            this.orderAmount = orderAmount;
        }
    }
    

    1.3 多级分组

    • 把内层 groupingBy 传递给外层 groupingBy
    • n 级分组就会得到一个代表 n 级树形结构的 n 级 Map
    @Test
    public void multilevel() {
        List<OrderDTO> orderDTOS = Arrays.asList(new OrderDTO("1001", "20230101", 0, 30L),
                new OrderDTO("1002", "20230102", -1, 100L),
                new OrderDTO("1003", "20230103", 0, 50L));
    
        Map<Integer, Map<String, List<OrderDTO>>> map = orderDTOS.stream().collect(
                groupingBy(OrderDTO::getOrderStatus,   // 一级分类函数
                        groupingBy(OrderDTO::getOrderCode))); // 二级分类函数
    }
    

    1.4 分组收集

    @Test
    public void collect() {
        List<OrderDTO> orderDTOS = Arrays.asList(new OrderDTO("1001", "20230101", 0, 30L),
                new OrderDTO("1002", "20230101", 0, 100L),
                new OrderDTO("1003", "20230103", -1, 50L));
    
        Map<String, Long> collect = orderDTOS.stream().collect(
                groupingBy(OrderDTO::getTradeId, summingLong(OrderDTO::getOrderAmount)));
        System.out.println(collect);
    }
    

    打印结果:
    {20230101=130, 20230103=50}

    1.5 操作分组元素

    Java 9 新增两个收集器:Collectors.filtering 和 Collectors.flatMapping
    过滤操作 Collectors.filtering(Predicate predicate, Collector downstream)
    映射操作 Collectors.mapping(Function mapper, Collector downstream)

    Map<String, List<OrderDTO>> collect1 = orderDTOS.stream().collect(groupingBy(OrderDTO::getType, filtering(orderDO -> orderDO.getId() > 20, toList())));
    Map<String, List<Integer>> collect2 = orderDTOS.stream().collect(groupingBy(OrderDTO::getType, mapping(OrderDO::getId, toList())));
    
    Map<String, Set<String>> collect = goodsList.stream().collect(
            groupingBy(Goods::getName,
                    flatMapping(goods -> maps.get(goods.getName()).stream(), Collectors.toSet())));
    

    2. 分区 Collectors.partitioningBy()

    • 分区是分组的特殊情况:由一个谓词(返回一个布尔值的函数)作为分类函数,它称分区函数
    • 分区函数返回一个布尔值,最多可以分为两组:true是一组,false是一组
    • Map 的键类型是 Boolean
    @Test
    public void partition() {
        List<OrderDTO> orderDTOS = Arrays.asList(new OrderDTO("1001", 30L),
                new OrderDTO("1002", 50L), new OrderDTO("1003", 100L));
    
        Map<Boolean, List<OrderDTO>> map = orderDTOS.stream()
                .collect(partitioningBy(orderDO -> orderDO.getOrderAmount() > 50));
        System.out.println(JSON.toJSONString(map));
    
        // 获取值
        List<OrderDTO> result = map.get(true);
    }
    

    输出 map 值:

    {
        false: [
            {
                "orderAmount": 30,
                "tradeId": "1001"
            },
            {
                "orderAmount": 50,
                "tradeId": "1002"
            }
        ],
        true: [
            {
                "orderAmount": 100,
                "tradeId": "1003"
            }
        ]
    }
    

    相关文章

      网友评论

          本文标题:Java8 Stream 之分组与分区

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