java 1.8 stream使用总结+实战demo

stream是jdk1.8引入的一个新概念,把列表流stream化,然后再加工成我们想要的列表或者别的数据
我们经常会对列表list数据用for循环,用stream来替换for循环会更简洁。

盗图,我觉得这张图讲的很清楚

参考网友的图,我觉得这张图描述的很清楚,steam可以不断进行加工


Stream的api大体上分为两种:中间操作符和终止操作符

1.集合中的方法都有stream(),使用stream()把集合进行流化,例如 list.stream(),流化后可以使用stream的中间操作符和终止操作符,即使用stream提供的api处理集合。
2.中间操作符就是Lambda表达式的链式操作,可以链式对流进行操作,操作完后还是返回流
3.终止操作符就是用来结束流的,数据经过中间加工操作,最后通过终止操作符对数据进行收集或者消费的,数据到了终止操作这里就不会向下流动了,终止操作符只能使用一次

中间操作符:
  1. filter
    可以通过 filter 方法将一个流转换成另一个子集流

  2. map
    可以通过map 方法将一个流映射成另一个流

  3. sort
    在流里面进行排序

  4. limit
    限制流,例如只取前流的前几个元素

  5. skip
    跳过操作,例如跳过流的前几个元素

  6. count
    统计个数,正如旧集合 Collection 当中的 size 方法一样,流提供 count 方法来数一数其中的元素个数

终止操作符:
  1. collect
    收集操作,将所有数据收集起来,Stream 的核心在于Collectors,常用的Collectors.toSet()、Collectors.toList()、Collectors.groupingBy()
  2. count
    统计操作,统计最终的数据个数。
  3. findFirst、findAny
    查找操作,查找第一个、查找任何一个 返回的类型为Optional。
  4. noneMatch、allMatch、anyMatch
    匹配操作,数据流中是否存在符合条件的元素 返回值为bool 值。
  5. min、max
    最值操作,需要自定义比较器,返回数据流中最大最小的值。
  6. reduce
    规约操作,将整个数据流的值规约为一个值,count、min、max底层就是使用reduce。
  7. forEach、forEachOrdered
    遍历操作,这里就是对最终的数据进行消费了。
  8. toArray
    数组操作,将数据流的元素转换成数组。

实战demo

例如下面有一个列表数据,我们要把列表按创建时间来 分组(按年月格式分组)、倒叙,来获取一个分组后的集合
按年月yyyy-MM格式分组
在这里插入图片描述

    public List<User> initData(){
        List<User> userList = new ArrayList<>();
        User user1 = new User(1,"测试1","2019-12-27 11:33:48");
        User user2 = new User(2,"测试2","2020-01-21 11:33:48");
        User user3 = new User(3,"测试3","2020-02-21 11:32:48");
        User user4 = new User(4,"测试4","2020-02-21 11:31:48");
        User user5 = new User(5,"测试5","2020-01-23 10:33:48");

        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);
        userList.add(user5);
        return userList;
    }
    @Data
    public static class User{
        int id;
        String name;
        String creteTime;

        public User(int id,String name,String creteTime){
            this.id = id;
            this.name = name;
            this.creteTime = creteTime;
        }


    }

方式一:使用for循环

        List<Map<String,Object>> newListGroupByMonth = new ArrayList<>();
        //按月分组
        Set<String> yearMonthList = new TreeSet<>(new Comparator(){
            @Override
            public int compare(Object element1, Object element2) {//按时间倒叙
                int result = element2.toString().compareTo(element1.toString());
                return result;
            }
        });
        //获取月份数组
        for(User user : userList){
            String createTime = dataformat(user.getCreteTime(), "yyyy-MM");
            yearMonthList.add(createTime);
        }
        //根据月份分组,获取每个月份的列表数据
        for(String yearMonth : yearMonthList){
            //每个月份的数据列表
            List<User> users = new ArrayList<>();
            for(User user : userList){
                String createTime = dataformat(user.getCreteTime(), "yyyy-MM");
                if(yearMonth.equals(createTime)){
                    users.add(user);
                }
            }
            Map<String,Object> data = new HashMap<>();
            data.put("yearMonth",yearMonth);
            data.put("list",users);
            newListGroupByMonth.add(data);
        }

方式二:使用stream

        List<Map<String,Object>> newListGroupByMonth = userList.stream()
                .map(m->dataformat(m.getCreteTime(),"yyyy-MM"))
                .sorted( (element1, element2)->element2.toString().compareTo(element1.toString()))
                .collect(Collectors.toSet())
                .stream()
                .map(yearMonth->{
                    //按月分组
                    List curUserList = userList.stream().filter(user->yearMonth.equals(dataformat(user.getCreteTime(),"yyyy-MM"))).collect(Collectors.toList());
                    Map<String,Object> data = new HashMap<>();
                    data.put("yearMonth",yearMonth);
                    data.put("list",curUserList);
                    return data;
                }).collect(Collectors.toList());

可以看到使用stream方式没有用到for循环,代码也简洁了不少
上面的代码运行起来看到实现的功能都是一样的,都是把列表进行按月分组

注:
要是时间都是年月yyyy-MM这种格式的话,可以直接使用Collectors.groupingBy(User::getCreateTime)分组

上述demo的所有代码

public class StreamTest {

    /**
     * 使用for循环
     */
    @Test
    public void TestByFor() {
        List<User> userList = initData();
        /****************方式一start:for循环**********************/
        List<Map<String,Object>> newListGroupByMonth = new ArrayList<>();
        //按月分组
        Set<String> yearMonthList = new TreeSet<>(new Comparator(){
            @Override
            public int compare(Object element1, Object element2) {//按时间倒叙
                int result = element2.toString().compareTo(element1.toString());
                return result;
            }
        });
        //获取月份数组
        for(User user : userList){
            String createTime = dataformat(user.getCreteTime(), "yyyy-MM");
            yearMonthList.add(createTime);
        }
        //根据月份分组,获取每个月份的列表数据
        for(String yearMonth : yearMonthList){
            //每个月份的数据列表
            List<User> users = new ArrayList<>();
            for(User user : userList){
                String createTime = dataformat(user.getCreteTime(), "yyyy-MM");
                if(yearMonth.equals(createTime)){
                    users.add(user);
                }
            }
            Map<String,Object> data = new HashMap<>();
            data.put("yearMonth",yearMonth);
            data.put("list",users);
            newListGroupByMonth.add(data);
        }
        /****************方式一end:for循环**********************/
        printData(newListGroupByMonth);

    }

    /**
     * 使用stream
     */
    @Test
    public void TestByStream() {
        List<User> userList = initData();
        /****************方式二start:stream**********************/
        List<Map<String,Object>> newListGroupByMonth = userList.stream()
                .map(m->dataformat(m.getCreteTime(),"yyyy-MM"))
                .sorted( (element1, element2)->element2.toString().compareTo(element1.toString()))
                .collect(Collectors.toSet())
                .stream()
                .map(yearMonth->{

                    List curUserList = userList.stream().filter(user->yearMonth.equals(dataformat(user.getCreteTime(),"yyyy-MM"))).collect(Collectors.toList());
                    Map<String,Object> data = new HashMap<>();
                    data.put("yearMonth",yearMonth);
                    data.put("list",curUserList);
                    return data;
                }).collect(Collectors.toList());
        /****************方式二end:stream**********************/
        printData(newListGroupByMonth);

    }

    /**
     * 初始化数据
     * @return
     */
    public List<User> initData(){
        List<User> userList = new ArrayList<>();
        User user1 = new User(1,"测试1","2019-12-27 11:33:48");
        User user2 = new User(2,"测试2","2020-01-21 11:33:48");
        User user3 = new User(3,"测试3","2020-02-21 11:32:48");
        User user4 = new User(4,"测试4","2020-02-21 11:31:48");
        User user5 = new User(5,"测试5","2020-01-23 10:33:48");

        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);
        userList.add(user5);
        return userList;
    }

    /**
     * 打印列表数据
     * @param newListGroupByMonth
     */
    public void printData(List<Map<String,Object>> newListGroupByMonth){
        newListGroupByMonth.stream().forEach(m->{
            System.out.println("当前月份:"+m.get("yearMonth"));
            List<User> curUsers = (List<User>)m.get("list");
            curUsers.stream().forEach(user-> System.out.println("id:"+user.getId()+",name:"+user.name+",createTime:"+user.getCreteTime()));
            System.out.println("-------------------------------");
        });
    }


    @Data
    public static class User{
        int id;
        String name;
        String creteTime;

        public User(int id,String name,String creteTime){
            this.id = id;
            this.name = name;
            this.creteTime = creteTime;
        }


    }

    /**
     * 格式化时间
     *
     * @param data
     * @param format
     * @return
     */
    public static String dataformat(String data, String format) {
        SimpleDateFormat sformat = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = sformat.parse(data);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return sformat.format(date);
    }
}

参考
Java 之 Stream 流
玩转Java8Stream(一、从零认识Stream)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值