JDK8都发行5年多了,你还不会使用Stream流和Lambda表达式吗?

前言:

第一次听说Stream流,还是在2018年刚工作的时候,我向一个同事请教某些问题,他跟我说JDK8新增了Stream流的特性,让我学习一下,当时我们公司根本没有人使用,我也没有去学习。我一次开始使用Stream流和Lambda表达式已经是2019年了,已经快过去一年了,Stream流和Lambda表达式的使用,确实方面开发和提高了效率,下面我分享一些常用的用法:

Stream流:

一、简介:

Stream流是对集合对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,例如:分组、过滤、去重等操作,它就像SQL语句一样简单。Stream流中可以使用Lambda表达式,提高编程效率和程序可读性。Stream流具有代码简洁和多核友好的优点。

二、常见方法汇总:

操作类型接口方法
中间操作concat() distinct() filter() flatMap() limit() map() peek() skip() sorted() parallel() sequential() unordered()
结束操作allMatch() anyMatch() collect() count() findAny() findFirst() forEach() forEachOrdered() max() min() noneMatch() reduce() toArray()

三、常见方式使用:

0.数据准备:

    List<StudentVO> studentList=new ArrayList<>();
    studentList.add(new StudentVO("1","小张","1",8,null,"北京顺义"));
    studentList.add(new StudentVO("2","小韩","2",14,null,"北京顺义"));
    studentList.add(new StudentVO("3","小王","1",20,null,"北京密云"));
    studentList.add(new StudentVO("4","小周","1",13,null,"北京通州"));
    studentList.add(new StudentVO("4","小李","2",7,null,"北京平谷"));

1.中间操作:

  • map()用法:
        //用法一:
        List<String> addressList=studentList.stream().map(StudentVO::getAddress).collect(Collectors.toList());
        System.out.println("map()用法一: "+addressList.toString());
        //用法二:
        List<Integer> ageList=studentList.stream().map(x ->x.getAge()).collect(Collectors.toList());
        System.out.println("map()用法二: "+ageList.toString());
        //用法三:
        List<StudentDO> newStudentList=studentList.stream().map(x ->{
            StudentDO studentDO = new StudentDO();
            studentDO.setId(x.getId());
            studentDO.setName(x.getName());
            studentDO.setSex(x.getSex());
            return studentDO;
        }).collect(Collectors.toList());
        System.out.println("map()用法三: "+newStudentList.toString());
  •  sorted()用法:
        //自然排序:(StudentVO需要实现Comparable<E>接口,重写compareTo()方法)
        List<StudentVO> studentVOAscList=studentList.stream().sorted().collect(Collectors.toList());
        System.out.println("自然排序: "+studentVOAscList.toString());
        //自然序逆序:
        List<StudentVO> studentVODescList=studentList.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        System.out.println("自然序逆序: "+studentVODescList.toString());
        //自定义升序:
        List<StudentVO> studentVOSortedAscList=studentList.stream().sorted(Comparator.comparing(StudentVO::getSex)).collect(Collectors.toList());
        System.out.println("自定义升序: "+studentVOSortedAscList.toString());
        //自定义降序:
        List<StudentVO> studentVOSortedDescList=studentList.stream().sorted(Comparator.comparing(StudentVO::getSex).reversed()).collect(Collectors.toList());
        System.out.println("自定义降序: "+studentVOSortedDescList.toString());
  • filter()(过滤)用法:
        List<StudentVO> studentVOFilterList1=studentList.stream().filter(obj ->"北京顺义".equals(obj.getAddress())).collect(Collectors.toList());
        System.out.println("北京顺义的学生: "+studentVOFilterList1.toString());
        List<StudentVO> studentVOFilterList2=studentList.stream().filter(obj ->obj.getAge()>=18).collect(Collectors.toList());
        System.out.println("成年的学生: "+studentVOFilterList2.toString());
  •  distinct()(去重)用法:
        List<StudentVO> studentVODistinctList=studentList.stream().distinct().collect(Collectors.toList());
  •  limit()(截取)用法:
        List<StudentVO> studentVOLimitList=studentList.stream().limit(2).collect(Collectors.toList());
  • skip()(跳过)用法:skip(Long n)
        List<StudentVO> studentVOSkipList=studentList.stream().skip(2).collect(Collectors.toList());

2.结束操作: 

  • forEach()用法:
        studentList.stream().forEach(x ->x.setAddress(x.getName()+":"+x.getPhone()));
  • reduce()归约:

流由一个个元素组成,归约就是将一个个元素“折叠”成一个值,如求和、求最值、求平均值都是归约操作。

        // 方式一:自定义Lambda表达式求和
        int age1 = studentList.stream().map(StudentVO::getAge).reduce(0, (x1,x2)->x1+x2);
        System.out.println("自定义Lambda表达式求和: "+age1);

        //方式二:使用Integer.sum函数求和
        int age2 = studentList.stream().map(StudentVO::getAge).reduce(0,Integer::sum);
        System.out.println("使用Integer.sum函数求和: "+age2);
        //注:Integer类还提供了min、max等一系列数值操作,当流中元素为数值类型时可以直接使用

        //方式三:使用数值流求和
        int age3 = studentList.stream().mapToInt(StudentVO::getAge).sum();
        System.out.println("使用数值流求和: "+age3);
        //注:
        // 将普通流转换成数值流的方法:mapToInt、mapToDouble、mapToLong
        // 每种数值流都提供了数值计算函数,如max、min、sum等
  • collect()收集器:

    收集器是对流经过筛选、映射、去重等中间操作进行后的整理,以不同的形式展现

        //计数:
        long count1 = studentList.stream().collect(Collectors.counting());
        long count2= studentList.stream().count();
        long count3= studentList.size();
        System.out.println("计数:"+"count1: "+count1+" count2: "+count2+" count3: "+count3);

        //最值:
        //例1:年龄最大的学生
        Optional<StudentVO> oldStudent =studentList.stream().collect(Collectors.maxBy(Comparator.comparingInt(StudentVO::getAge)));
        //例2:年龄最小的学生
        Optional<StudentVO> youngStudent =studentList.stream().collect(Collectors.minBy(Comparator.comparingInt(StudentVO::getAge)));
        System.out.println("年龄最大的学生: "+oldStudent.toString()+" 年龄最小的学生: "+youngStudent.toString());

        //求和:
        //例:计算所有学生年龄总和
        int sum = studentList.stream().collect(Collectors.summingInt(StudentVO::getAge));
        System.out.println("所有学生年龄总和: "+sum);
        //注:Java8提供了summingInt、summingLong、summingDouble

        //平均值:
        //例:计算所有学生的年龄平均值
        double avg  = studentList.stream().collect(Collectors.averagingInt(StudentVO::getAge));
        System.out.println("所有学生的年龄平均值: "+avg);
        //注:计算平均值时,不论计算对象是int、long、double,计算结果一定都是double

        //一次性计算所有归约操作:
        //Collectors.summarizingInt函数能一次性将最值、均值、总和、元素个数全部计算出来,并存储在对象IntSummaryStatistics中
        IntSummaryStatistics collectList = studentList.stream().collect(Collectors.summarizingInt(StudentVO::getAge));
        collectList.getCount();
        collectList.getMin();
        collectList.getMax();
        collectList.getSum();
        collectList.getAverage();
        System.out.println("一次性计算所有归约操作: "+collectList.toString());

        //连接字符串:
        //例:指定分隔符,连接姓名字符串
        String names = studentList.stream().map(StudentVO::getName).collect(Collectors.joining(", "));
        System.out.println("指定分隔符,连接姓名字符串: "+names);

        //一般性的归约操作(自定义一个归约操作):以后细研究,先学会基本使用
        //自定义归约操作,需要使用Collectors.reducing函数,该函数接收三个参数:
        //第一个参数为归约的初始值、第二个参数为归约操作进行的字段、第三个参数为归约操作的过程
        //例:计算所有学生年龄总和
        Integer sumAge = studentList.stream().collect(Collectors.reducing(0, StudentVO::getAge, (i, j) -> i + j));
        System.out.println("所有学生年龄总: "+sumAge);

        //#分组:
        //将流中的元素按照指定类别进行划分,类似于SQL语句中的GROUPBY。
        //一级分组:
        //例:将所有学生分为小学、初中、高中、大学
        //注:返回Map<String,List<StudentVO>>类型
        Map<String,List<StudentVO>> result1 = studentList.stream()
                .collect(Collectors.groupingBy((studentVO)->{
                    if(studentVO.getAge()>=7&&studentVO.getAge()<12){
                        return "小学";
                    } else if(studentVO.getAge()>=12&&studentVO.getAge()<15){
                        return "初中";
                    }else if(studentVO.getAge()>=15&&studentVO.getAge()<18){
                        return "高中";
                    }else if(studentVO.getAge()>=18&&studentVO.getAge()<22){
                        return "大学";
                    }
                    return "其他";
                }));
        System.out.println("一级分组: "+result1.toString());

        //二级分组:
        //例:将所有学生分为小学、初中、高中、大学,并且按男女分组
        //注:返回Map<String, Map<String, List<StudentVO>>>类型
        Map<String, Map<String, List<StudentVO>>> result2 = studentList.stream()
                .collect(Collectors.groupingBy((studentVO) -> {
                            if (studentVO.getAge() >= 7 && studentVO.getAge() < 12) {
                                return "小学";
                            } else if (studentVO.getAge() >= 12 && studentVO.getAge() < 15) {
                                return "初中";
                            } else if (studentVO.getAge() >= 15 && studentVO.getAge() < 18) {
                                return "高中";
                            } else if (studentVO.getAge() >= 18 && studentVO.getAge() < 22) {
                                return "大学";
                            }
                            return "其他";
                        }, Collectors.groupingBy(x->{
                            if(x.getSex().equals("1")){
                                return "男";
                            }
                            return "女";
                        })
                ));

        System.out.println("二级分组: "+result2.toString());

 3.常用方法:

  • List转Map:
       Map<String, Object> map = list.stream().collect(Collectors.toMap(Student::getId, Student));
  •  List降序排列:

       List<Student> bjProcessTaskList = list.stream().
               sorted(Comparator.comparing(Student::getCreateTime).reversed()).collect(Collectors.toList());
  • List转String:
       String names = studentList.stream().map(StudentVO::getName).collect(Collectors.joining(", "));
      
  • Map遍历: 
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
map.forEach((key, value)->{
           System.out.println("key:"+ key);
           System.out.println("value:"+ value);
           });
  • 分组求和(2020-08-21):  
--IntSummaryStatistics集合,包含了max,min,sum,count
Map<String, IntSummaryStatistics> collect = list.stream().collect(Collectors.groupingBy(StudentVO::getName, Collectors.summarizingInt(StudentVO::getGrade)));
--分组求和
Map<String, int> collect = list.stream().collect(Collectors.groupingBy(StudentVO::getName, Collectors.summingInt(StudentVO::getGrade)));
  •  排序处理空指针(2021-05-07):  
Comparator.nullsLast(Long::compareTo)
  •   排序多个字段比较(2021-05-07):  
Comparator.comparing(XXX::getOrderId).reversed().thenComparing(XXX::getTaskId, Comparator.nullsLast(Long::compareTo)))

 

Lambda表达式:

1.基本语法:

() -> expression
或
(parameters) -> expression
或
parameters -> expression
或
() ->{ statements;}
或
(parameters) ->{ statements;}
或
parameters ->{ statements;}

2.双冒号::的用法:

类名::方法名 
注:此处没有()
例:
Lambda表达式: person -> person.getAge();
使用双冒号: Person::getAge
表达式:new HashMap<>()
使用双冒号:HsahMap :: new

 

 

 

 

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hanxiaozhang2018

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值