文档章节

JDK8 Collectors 使用篇(四)

kaishui
 kaishui
发布于 2016/10/07 15:20
字数 1401
阅读 196
收藏 1

#Collectors 使用 在之前篇章中,我们探讨了Lambdas函数式接口编程Stream的使用。现在拿collectors 耍耍.

Collectors是一个reduce操作,通过collectors 可以把一个结合转换成另外一个集合collection,Map, 或者一个值。

来看看collectors能干什么:

##1.分组 groupby


public class Jdk8_collector_groupby_test {

    private static class User {
        private String name;
        private String password;

       //省略getter setter
    }

    public static void main(String[] args) {
        List<User> userList = constructUserList();

        //使用JDK8 按照名字分组
        Map<String, List<User>> userMaps = userList.stream().collect(Collectors.groupingBy(u -> u.getName()));
        //按照密码分组
        Map<String, List<User>> userPasswordMaps = userList.stream().collect(Collectors.groupingBy(u -> u.getPassword()));

        userMaps.forEach((key, groupUser) -> {
            System.out.println("---------------- group by user name = " + key + "----------");
            groupUser.forEach(u -> System.out.println(u.getPassword()));
        });
        userPasswordMaps.forEach((key, groupUser) -> {
            System.out.println("----------------  group by user password = " + key + "----------");
            groupUser.forEach(u -> System.out.println(u.getName()));
        });

        //上面的例子想想用JKD7写,表示博主很懒
        Map<String, List<User>> userJdk7Map = new HashMap<String, List<User>>();
        //按照名字分组
        for (User u : userList) {
            if (userJdk7Map.containsKey(u.getName())) {//如果map中已经存在则add 到groupList中
                List<User> groupTempUserList = userJdk7Map.get(u.getName());
                groupTempUserList.add(u);
            }else{//增加一个新的
                List<User> groupTempUserList = new ArrayList<User>();
                groupTempUserList.add(u);
                userJdk7Map.put(u.getName(), groupTempUserList);
            }
        }

        //按照密码分组 大写略 参考名字分组

        //jdk7 打印
        for (Map.Entry<String, List<User>> entry : userJdk7Map.entrySet()) {
            System.out.println("---------------- jdk7 group by user name = " + entry.getKey() + "----------");
            for (User user : entry.getValue()) {
                System.out.println( user.getPassword());
            }
        }

    }

    /**
     * 构造一个用户列表
     * @return
     */
    private static List<User> constructUserList() {
        List<User> userList = new ArrayList<User>();
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                User u = new User();
                u.setPassword("password" + j);
                u.setName("name" + i);
                userList.add(u);
            }
        }
        return userList;
    }
}


运行结果:

---------------- group by user name = name1----------
password0
password1
---------------- group by user name = name0----------
password0
password1
----------------  group by user password = password0----------
name0
name1
----------------  group by user password = password1----------
name0
name1
---------------- jdk7 group by user name = name1----------
password0
password1
---------------- jdk7 group by user name = name0----------
password0
password1

如果感兴趣,可以点击进Collectors.groupingBy看看,参数就是一个Function,根据条件进行分组。

##2. 最经常使用的,集合转变成其他集合

public class Jdk8_collector_reduce_test {

    private static class User {
        private String name;
        private String password;
        //getter setter
    }

    public static void main(String[] args) {
        List<User> userList = constructUserList();

        //使用JDK8 提取所有名字
        List<String> userStrList = userList.stream().map(User::getName).collect(Collectors.toList());
        //把名字提取出来,并转化成name set
        Set<String> userNameSet = userList.stream().map(User::getName).collect(Collectors.toSet());

        //转化成<name, password> 结构的map,注意: key 不能重复,使用distinct去重复
        Map<String, String> userNameMap = userList.stream().distinct().collect(Collectors.toMap(u -> u.getName(), u -> u.getPassword()));

        //提取成 Map<name, User>
        Map<String, User> userMap = userList.stream().distinct().collect(Collectors.toMap(u -> u.getName(), Function.identity()));

        //提取成 Map<name, String> 合并
        Map<String, String> userMergeDulicateMap = userList.stream()
                .collect(Collectors.toMap(User::getName, User::getPassword, (t1, t2) ->{
                    return t1 + "," + t2;
                }));
        
        System.out.println("---------------打印 list -------------");
        userStrList.forEach(System.out::println);

        System.out.println("---------------打印 set -------------");
        userNameSet.forEach(System.out::println);

        System.out.println("---------------打印 map -------------");
        userNameMap.forEach((key, val) -> {
            System.out.println(key + "---" + val);
        });

        System.out.println("---------------打印 user map -------------");
        userMap.forEach((key, val) -> {
            System.out.println(key + "---" + val.getPassword());
        });

        System.out.println("---------------打印 userMergeDulicateMap -------------");
        userMergeDulicateMap.forEach((key, val) -> {
            System.out.println(key + "---" + val);
        });

    }

    /**
     * 构造一个用户列表
     *
     * @return
     */
    private static List<User> constructUserList() {
        List<User> userList = new ArrayList<User>();
        for (int i = 0; i < 4; i++) {
            User u = new User();
            u.setPassword("password" + i);
            u.setName("name" + i);
            userList.add(u);
            userList.add(u);
        }
        return userList;
    }
}

运行结果:

---------------打印 list -------------
name0
name0
name1
name1
name2
name2
name3
name3
---------------打印 set -------------
name3
name2
name1
name0
---------------打印 map -------------
name3---password3
name2---password2
name1---password1
name0---password0
---------------打印 user map -------------
name3---password3
name2---password2
name1---password1
name0---password0
---------------打印 userMergeDulicateMap -------------
name3---password3,password3
name2---password2,password2
name1---password1,password1
name0---password0,password0

##3. Collectors API使用

下面例子介绍部分collectors API的使用,主要有:maxBy、joining、counting、summingInt、partitioningBy、summarizingInt 的使用,如果感兴趣可以琢磨一下collectors API的内部使用,理解一下downstream ,和前面章节介绍的 predicate、function、consumer 就很容易融入到自己代码中.

public class Jdk8_collector_operation_test {

    private static class User {
        private String name;
        private String password;

       	//省略getter setter
    }

    public static void main(String[] args) {
        List<User> userList = constructUserList();

        //1.maxBy求最大值
        User user = userList.stream().collect(Collectors.collectingAndThen(
                Collectors.maxBy((t1, t2) ->t1.getPassword().length() - t2.getPassword().length()), Optional::get));

        //2.joining 合并,通过分隔符“,”合并用户名称
        String userName = userList.stream().map(User::getName).collect(Collectors.joining(","));

        //3.summingInt 统计总和
        int totalNameLen = userList.stream().map(User::getName).collect(Collectors.summingInt(String::length));

        //4.counting 集合个数
        Long count = userList.stream().map(User::getName).collect(Collectors.counting());

        //5.groupingBy 分组, counting统计元素个数,按照名字分组,并统计分组元素个数
        Map<String, Long> groupNameCount = userList.stream().collect(Collectors.groupingBy(User::getName, Collectors.counting()));

        //6.partitioningBy 分片 根据Predicate条件分片
        Map<Boolean, List<User>> partitioningMap = userList.stream()
                .collect(Collectors.partitioningBy(u -> u.getPassword().indexOf("1") >= 0, Collectors.toList()));

        //7.summarizingInt 对数据的汇总统计 返回一个统计类IntSummaryStatistics
        IntSummaryStatistics intSummaryStatistics = userList.stream().map(User::getPassword)
                .collect(Collectors.summarizingInt(String::length));


        System.out.println( "password最大长度的:" + user.getName());
        System.out.println("所用用户名:" + userName);
        System.out.println("所有用户名长度:" + totalNameLen);
        System.out.println("集合个数:" + count);
        groupNameCount.forEach((key, val) -> {
            System.out.println(key + " ---打印分组元素个数--- " + val);
        });

        partitioningMap.forEach((key, val) -> {
            System.out.println(key + " ---打印分片元素--- ");
            val.forEach(u -> {
                System.out.println( u.getName() );
            });
        });

        System.out.println("------汇总统计----平均值:" + intSummaryStatistics.getAverage());
        System.out.println("------汇总统计----元素个数:" + intSummaryStatistics.getCount());
        System.out.println("------汇总统计----最小值:" + intSummaryStatistics.getMin());
        System.out.println("------汇总统计----最大值:" + intSummaryStatistics.getMax());
        System.out.println("------汇总统计----累加:" + intSummaryStatistics.getSum());

    }

    /**
     * 构造一个用户列表
     *
     * @return
     */
    private static List<User> constructUserList() {
        List<User> userList = new ArrayList<User>();
        for (int i = 0; i < 4; i++) {
            User u = new User();
            u.setPassword("password" + i);
            u.setName("name" + i);
            userList.add(u);
            userList.add(u);
        }
        return userList;
    }
}

返回结果:

password最大长度的:name0
所用用户名:name0,name0,name1,name1,name2,name2,name3,name3
所有用户名长度:40
集合个数:8
name3 ---打印分组元素个数--- 2
name2 ---打印分组元素个数--- 2
name1 ---打印分组元素个数--- 2
name0 ---打印分组元素个数--- 2
false ---打印分片元素--- 
name0
name0
name2
name2
name3
name3
true ---打印分片元素--- 
name1
name1
------汇总统计----平均值:9.0
------汇总统计----元素个数:8
------汇总统计----最小值:9
------汇总统计----最大值:9
------汇总统计----累加:72

JDK8 API使用很多时候耐心点看就能明白作者这样设计的巧妙,还是要多用,即使一开始不熟悉,用起来很别扭,应该用着用着就爱上了。

© 著作权归作者所有

共有 人打赏支持
kaishui
粉丝 52
博文 12
码字总数 10711
作品 0
广州
程序员
JDK8 Stream 从入门到装逼(三)

在lambdas中,可以看到lambda表达式让代码更加简洁、干净、容易理解,并允许不需要创建一个类就可以达到目的。lambdas很好的帮助开发人员更好的表达片段代码的意思,Stream对于集合提供一个抽...

kaishui
2016/09/06
1K
11
JDK之伪分享的情况下该使用填充还是@Contended

注意:JEP142规范,Reduce Cache Contention on Specified Fields。 1.伪分享情况下,JDK8上,偏向于使用@Contended 伪分享的情况下,可以使用填充和JDK8的@Contended注解。 但是实验结果证明...

汉斯-冯-拉特
06/30
0
0
java8函数式编程--收集器collector

java8的stream api能很方便我们对数据进行统计分类等工作,以前我们写的很多统计数据的代码往往是循环迭代得到的,不说别人看不懂,自己的代码放久了也要重新看一段时间才能看得懂。现在,j...

JoshuaShaw
2015/08/04
0
2
skywalking 5.X 分布式链路跟踪 使用笔记

skywalking 简介(链路跟踪与分析) 随着业务越来越复杂,企业应用也进入了分布式服务化的阶段,随着模块的不断增多,一次请求可能会涉及到十几个甚至几十个服务的协同处理,那么如何准确快速...

不会飞的小龙人
08/01
0
0
《字符串连接你用+还是用StringBuilder》续

前言 前面的一篇文章《字符串连接你用+还是用StringBuilder》,有朋友找我反馈了一些问题,其中一位朋友说JDK10下生成的字节码跟文章中并不一样,这里继续看下是什么情况。 问题描述 如下图,...

超人汪小建
07/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

原型模式

1、原型模式-定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 克隆(浅度克隆->拷贝值类型或者引用,深度克隆->创建新的对象,开辟新的内存) 例如客户端知道抽象Pro...

阿元
今天
29
0
awk命令扩展使用操作

awk 中使用外部shell变量 示例1 [root@centos01 t1022]# A=888[root@centos01 t1022]# echo "" | awk -v GET_A=$A '{print GET_A}'888[root@centos01 t1022]# echo "aaaaaaaaaaaaa" | aw......

野雪球
今天
27
0
深入解析MySQL视图VIEW

Q:什么是视图?视图是干什么用的? A:视图(view)是一种虚拟存在的表,是一个逻辑表,本身并不包含数据。作为一个select语句保存在数据字典中的。   通过视图,可以展现基表的部分数据;...

IT--小哥
今天
33
0
虚拟机学习之二:垃圾收集器和内存分配策略

1.对象是否可回收 1.1引用计数算法 引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时候计数器值为0的对象就是不可能...

贾峰uk
今天
20
0
smart-doc功能使用介绍

smart-doc从8月份底开始开源发布到目前为止已经迭代了几个版本。在这里非常感谢那些敢于用smart-doc去做尝试并积极提出建议的社区用户。因此决定在本博客中重要说明下smart-doc的功能,包括使...

上官胡闹
昨天
32
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部