JDK8之Stream流及Lambda表达式简介说明
下文笔者讲述Stream的常见方法简介说明,如下所示
Stream流简介
Stream流是对集合对象功能的增强 它专注于对集合对象进行各种非常便利、高效的聚合操作 如: 分组、过滤、去重等操作 它就像SQL语句一样简单 Stream流中可以使用Lambda表达式 提高编程效率和程序可读性 Stream流具有代码简洁和快速开发的优点
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
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。