Bootstrap

Collectors.groupingBy和peek函数用法

前述

Collectors.groupingBy:根据一个或多个属性对集合中的项目进行分组
peek函数:改变对象里的值

实体类

public class Product {
    private Long id;
    private Integer num;
    private BigDecimal price;
    private String name;
    private String category;

    public Product(Long id, Integer num, BigDecimal price, String name, String category) {
        this.id = id;
        this.num = num;
        this.price = price;
        this.name = name;
        this.category = category;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", num=" + num +
                ", price=" + price +
                ", name='" + name + '\'' +
                ", category='" + category + '\'' +
                '}';
    }
}

测试代码–Collectors.groupingBy

public class test {
    public static void main(String[] args) {
        Product prod1 = new Product(1L, 1, new BigDecimal("15.5"), "面包", "零食");
        Product prod2 = new Product(2L, 2, new BigDecimal("20"), "饼干", "零食");
        Product prod3 = new Product(3L, 3, new BigDecimal("30"), "月饼", "零食");
        Product prod4 = new Product(4L, 3, new BigDecimal("10"), "青岛啤酒", "啤酒");
        Product prod5 = new Product(5L, 10, new BigDecimal("15"), "百威啤酒", "啤酒");
        List<Product> prodList = Lists.newArrayList(prod1, prod2, prod3, prod4, prod5);
        System.out.println("===================按照类目分组=================================");
        Map<String, List<Product>> prodMap1 = prodList.stream().collect(Collectors.groupingBy(Product::getCategory));
        for (String key : prodMap1.keySet()) {
            System.out.println(key + ": " + prodMap1.get(key).toString());
        }
        // 运行结果
        // 啤酒: [Product{id=4, num=3, price=10, name='青岛啤酒', category='啤酒'}, Product{id=5, num=10, price=15, name='百威啤酒', category='啤酒'}]
        // 零食: [Product{id=1, num=1, price=15.5, name='面包', category='零食'}, Product{id=2, num=2, price=20, name='饼干', category='零食'}, Product{id=3, num=3, price=30, name='月饼', category='零食'}]

        System.out.println("===================按照几个属性拼接分组===========================");
        Map<String, List<Product>> prodMap2 = prodList.stream().collect(Collectors.groupingBy(item -> item.getCategory() + "_" + item.getName()));
        for (String key : prodMap2.keySet()) {
            System.out.println(key + ": " + prodMap2.get(key).toString());
        }
        // 运行结果
        // 零食_月饼: [Product{id=3, num=3, price=30, name='月饼', category='零食'}]
        // 零食_面包: [Product{id=1, num=1, price=15.5, name='面包', category='零食'}]
        // 啤酒_百威啤酒: [Product{id=5, num=10, price=15, name='百威啤酒', category='啤酒'}]
        // 啤酒_青岛啤酒: [Product{id=4, num=3, price=10, name='青岛啤酒', category='啤酒'}]
        // 零食_饼干: [Product{id=2, num=2, price=20, name='饼干', category='零食'}]

        System.out.println("=====================根据不同条件分组==============================");
        Map<String, List<Product>> prodMap3 = prodList.stream().collect(Collectors.groupingBy(item -> {
            if (item.getNum() < 3) {
                return "more";
            } else {
                return "other";
            }
        }));
        for (String key : prodMap3.keySet()) {
            System.out.println(key + ": " + prodMap3.get(key).toString());
        }
        // 运行结果
        // other: [Product{id=3, num=3, price=30, name='月饼', category='零食'}, Product{id=4, num=3, price=10, name='青岛啤酒', category='啤酒'}, Product{id=5, num=10, price=15, name='百威啤酒', category='啤酒'}]
        // more: [Product{id=1, num=1, price=15.5, name='面包', category='零食'}, Product{id=2, num=2, price=20, name='饼干', category='零食'}]

        System.out.println("=================多级分组(二级分组)============================");
        // 要实现多级分组,我们可以使用一个由双参数版本的Collectors.groupingBy工厂方法创建的收集器,它除了普通的分类函数之外,还可以接受collector类型的第二个参数。
        // 那么要进 行二级分组的话,我们可以把一个内层groupingBy传递给外层groupingBy,并定义一个为流中项目分类的二级标准。
        Map<String, Map<String, List<Product>>> prodMap4 = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.groupingBy(item -> {
            if (item.getNum() < 3) {
                return "more";
            } else {
                return "other";
            }
        })));
        for (String key : prodMap4.keySet()) {
            System.out.println(key + ": " + prodMap4.get(key).toString());
        }
        // 运行结果
        // 啤酒: {other=[Product{id=4, num=3, price=10, name='青岛啤酒', category='啤酒'}, Product{id=5, num=10, price=15, name='百威啤酒', category='啤酒'}]}
        // 零食: {other=[Product{id=3, num=3, price=30, name='月饼', category='零食'}], 3=[Product{id=1, num=1, price=15.5, name='面包', category='零食'}, Product{id=2, num=2, price=20, name='饼干', category='零食'}]}

        System.out.println("=====================按子组收集数据  求总数======================");
        Map<String, Long> prodMap5 = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.counting()));
        for (String key : prodMap5.keySet()) {
            System.out.println(key + ": " + prodMap5.get(key).toString());
        }
        // 运行结果
        // 啤酒: 2
        // 零食: 3

        System.out.println("===============================按子组收集数据 求和====================");
        Map<String, Integer> prodMap6 = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.summingInt(Product::getNum)));
        for (String key : prodMap6.keySet()) {
            System.out.println(key + ": " + prodMap6.get(key).toString());
        }
        // 运行结果
        // 啤酒: 13
        // 零食: 6

        System.out.println("====================把收集器的结果转换为另一种类型==============================");
        Map<String, Product> prodMap7 = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(Product::getNum)), Optional::get)));
        for (String key : prodMap7.keySet()) {
            System.out.println(key + ": " + prodMap7.get(key).toString());
        }
        // 运行结果
        // 啤酒: Product{id=5, num=10, price=15, name='百威啤酒', category='啤酒'}
        // 零食: Product{id=3, num=3, price=30, name='月饼', category='零食'}

        System.out.println("=====================联合其他收集器=====================================");
        Map<String, Set<String>> prodMap8 = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.mapping(Product::getName, Collectors.toSet())));
        for (String key : prodMap8.keySet()) {
            System.out.println(key + ": " + prodMap8.get(key).toString());
        }
        // 运行结果
        // 啤酒: [青岛啤酒, 百威啤酒]
        // 零食: [面包, 饼干, 月饼]
    }
}

测试代码–peek

public class test {
    public static void main(String[] args) {
        Product prod1 = new Product(1L, 1, new BigDecimal("15.5"), "面包", "零食");
        Product prod2 = new Product(2L, 2, new BigDecimal("20"), "饼干", "零食");
        Product prod3 = new Product(3L, 3, new BigDecimal("30"), "月饼", "零食");
        Product prod4 = new Product(4L, 3, new BigDecimal("10"), "青岛啤酒", "啤酒");
        Product prod5 = new Product(5L, 10, new BigDecimal("15"), "百威啤酒", "啤酒");
        List<Product> prodList = Lists.newArrayList(prod1, prod2, prod3, prod4, prod5);
        
        System.out.println("===============================按子组收集数据 求和  不使用peek函数处理====================");
        Map<String, Integer> prodMap9 = prodList.stream()
                .peek(product -> product.setNum(product.getNum()))
                .collect(Collectors.groupingBy(Product::getCategory, Collectors.summingInt(Product::getNum)))
                .entrySet().stream().collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (v1, v2) -> v1,
                        HashMap::new
                ));
        for (String key : prodMap9.keySet()) {
            System.out.println(key + ": " + prodMap9.get(key).toString());
        }
        // 运行结果
        // 啤酒: 13
        // 零食: 6

        System.out.println("===============================按子组收集数据 求和  使用peek函数处理====================");
        Map<String, Integer> prodMap10 = prodList.stream()
                .peek(product -> product.setNum(product.getNum() + 2))
                .collect(Collectors.groupingBy(Product::getCategory, Collectors.summingInt(Product::getNum)))
                .entrySet().stream().collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (v1, v2) -> v1,
                        HashMap::new
                ));
        for (String key : prodMap10.keySet()) {
            System.out.println(key + ": " + prodMap10.get(key).toString());
        }
        // 运行结果
        // 啤酒: 17
        // 零食: 12
    }
}
;