Java8新特性-分组groupingBy-实战(三)

利用Java8 StreamAPI完成项目需求

需求

将一批数据转换成页面的格式,如下 表格1

IP类型次数
172.12.12.1QQ2
172.12.12.2微信1
172.12.12.2QQ2
public class Demo2 {

    public static class  ImageItem{

        private String id ;

        private String type ;

        private String ip ;

        private String account ;

        public ImageItem(String id, String type, String ip, String account) {
            this.id = id;
            this.type = type;
            this.ip = ip;
            this.account = account;
        }

        public String getId() {
            return id;
        }

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

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getIp() {
            return ip;
        }

        public void setIp(String ip) {
            this.ip = ip;
        }

        public String getAccount() {
            return account;
        }

        public void setAccount(String account) {
            this.account = account;
        }
    }

    public static void main(String[] args) {
        List<ImageItem> imageList = new ArrayList<>();
        ImageItem item1 = new ImageItem("1","微信","172.12.12.1","13912911111");
        imageList.add(item1);


        ImageItem item2 = new ImageItem("2","微信","172.12.12.1","13912911111");
        imageList.add(item2);

        ImageItem item3 = new ImageItem("3","QQ","172.12.12.2","13912911111");
        imageList.add(item3);

        ImageItem item4 = new ImageItem("4","QQ","172.12.12.2","13912922222");
        imageList.add(item4);

        ImageItem item5 = new ImageItem("5","微信","172.12.12.2","13912922222");
        imageList.add(item5);

        List<String> result = multiGroup(imageList);

        result.forEach(System.out::println);


    }

    public static List<String> multiGroup(List<ImageItem> imageList){
        Map<String, Map<String, Long>> res = imageList.stream()
                //先根据ip分组,再进行类型分组
                .collect(groupingBy(ImageItem::getIp, groupingBy(ImageItem::getType, counting())));
        List<String> result = new ArrayList<>();
        res.forEach((ip, valueMap) -> {
            valueMap.forEach((type, time) -> {
                String singleRes = "ip:" + ip + "通过" + type + "发送了" + time + "次";
                result.add(singleRes);
            });
        });
        return result;
}

打印结果:

ip:172.12.12.2通过QQ发送了2次
ip:172.12.12.2通过微信发送了1次
ip:172.12.12.1通过微信发送了2次

方法优化

由于业务需求多变,现在需要变换统计维度,如想做成下面的 表格2 效果:

账号类型次数
13912922222QQ1
13912922222微信1
13912911111QQ1
13912911111微信2

虽然再歇一个方法也是OK的 但是你会发现到处都是重复的逻辑,真正需要修改的就是第一次分组的逻辑

那就修改multiGroup方法,让调用方自己把分组的逻辑传给我吧,多传入一个Function

public static List<String> multiGroup(List<ImageItem> imageList, Function<ImageItem, String> function) {
        Map<String, Map<String, Long>> res = imageList.stream()
                //先根据ip分组,再进行类型分组
                .collect(groupingBy(function, groupingBy(ImageItem::getType, counting())));
        List<String> result = new ArrayList<>();
        res.forEach((ip, valueMap) -> {
            valueMap.forEach((type, time) -> {
                String singleRes = "ip:" + ip + "通过" + type + "发送了" + time + "次";
                result.add(singleRes);
            });
        });
        return result;
    }

调用代码

List<String> result = multiGroup(imageList, ImageItem::getAccount);//表格2效果的调用
List<String> result = multiGroup(imageList, ImageItem::getIp);//表格1效果的调用

版权声明:本文为wbb9019原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。