一个集合看穿lambda的用法

本文介绍 Java Stream API 的多种实用场景,包括数据转换、过滤、排序等操作,并演示如何使用 Optional 类型处理空值,提高代码健壮性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1  student 类

class Student {
    private int id;
    private String name;
    private int age;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2 常用例子汇总

       //转换成map,可以用在对一些集合进行分组,比如按学生年龄或姓名分组
    private void test1(List<Student> studentList) {
        log.info("----------------转换成map-------------------");
        Map<Integer, Student> studentMap = studentList.stream().collect(Collectors.toMap(Student::getId, Function.identity()));
        log.info("转换成map前:"+studentMap);
        Map<Integer, String> studentIdNameMap = studentList.stream().filter(s -> s.getId() == 1 || s.getId() == 2).collect(Collectors.toMap(Student::getAge, Student::getName));
        log.info("转换成map:"+studentIdNameMap);
    }

    //获取集合中的指定信息列表,可以用在去除集合中的冗余信息,比如我就需要获取学生的姓名列表
    private void test2(List<Student> studentList) {
        log.info("----------------获取集合中的指定信息列表-------------------");
        List<String> studentNames = studentList.stream().map(Student::getName).collect(Collectors.toList());
        log.info(""+studentNames);
    }

    //过滤,按条件获取子集合
    private void test3(List<Student> studentList) {
        log.info("----------------过滤-------------------");
        List<Student> studentList1 = studentList.stream().filter(s -> s.getAge() >= 20).collect(Collectors.toList());
        log.info(""+studentList1);
    }

    //排序,数据的正序或倒序排
    private void test4(List<Student> studentList) {
        log.info("----------------排序-------------------");
        List<Student> studentList1 = studentList.stream().sorted(Comparator.comparing(Student::getAge)).collect(Collectors.toList());
        log.info("正序:" + studentList1);
        studentList1 = studentList.stream().sorted(Comparator.comparing(Student::getAge).reversed()).collect(Collectors.toList());
        log.info("倒序:" + studentList1);
    }

    //递归,跟for循环作用一样
    private void test5(List<Student> studentList) {
        log.info("----------------递归-------------------");
        log.info("list集合递归:");
        studentList.forEach(s -> {
            System.out.print(s + " ");
        });
        log.info("");
        log.info(" map递归:");
        Map<Integer, String> stringIdNameMap = studentList.stream().collect(Collectors.toMap(Student::getId, Student::getName));
        stringIdNameMap.forEach((k, v) -> {
            System.out.print(k + ":" + v + " ");
        });
        log.info("");
    }

    //判空:orElse为空返回新的值, orElseGet为空get新值
    private void test6(List<Student> studentList) {
        log.info("----------------判空-------------------");
        List<Student> studentsNew = Optional.ofNullable(studentList).orElse(Arrays.asList(new Student(22, "aa", 101), new Student(22, "bb", 102)));
        log.info(""+studentsNew);
        studentsNew = Optional.ofNullable(studentList).orElseGet(() -> Arrays.asList(new Student(22, "aa", 101), new Student(22, "bb", 102)));
        log.info(""+studentsNew);
    }

    //去重
    private void test7(List<Student> studentList) {
        log.info("----------------去重-------------------");
        List<Integer> studentAges = studentList.stream().map(Student::getAge).distinct().collect(Collectors.toList());
        log.info(""+studentAges);
    }

    //截取
    private void test8(List<Student> studentList) {
        log.info("----------------截取-------------------");
        List<Student> studentListLimt = studentList.stream().limit(2).collect(Collectors.toList());
        log.info(""+studentListLimt);
    }

    //汇总,主要用在int,long,double类型的汇总,BigDecimal类型不支持
    private void test9(List<Student> studentList) {
        log.info("---------------- 汇总-------------------");
        IntSummaryStatistics intSummaryStatistics = studentList.stream().mapToInt(Student::getAge).summaryStatistics();
        log.info("sum:" + intSummaryStatistics.getSum() + ";max:" + intSummaryStatistics.getMax());

    }

    //条件校验,主要返回是否配某种校验条件
    private void test10(List<Student> studentList) {
        log.info("---------------- 条件校验-------------------");
        boolean checkStatus = studentList.stream().anyMatch(s -> s.getAge() > 10);
        log.info(""+checkStatus);
    }

    //集合转换,该用法很多实际情况下根据指定参数返回指定的结果值
    private void test11(List<Student> studentList) {
        log.info("----------------集合转换-------------------");
        List<Map<String, Integer>> studentNameAgeList = studentList.stream().map(s -> {
            Map<String, Integer> stringIntegerMap = new HashMap<>();
            stringIntegerMap.put(s.getName(), s.getAge());
            return stringIntegerMap;
        }).collect(Collectors.toList());
        log.info(""+studentNameAgeList);
    }

    //分组
    private void test12(List<Student> studentList) {
        log.info("----------------集合按年龄分组-------------------");
        Map<Integer, List<Student>> salaryPayrollItemGroups = studentList.stream().collect(Collectors.groupingBy(Student::getAge));
        salaryPayrollItemGroups.forEach((k, v) -> log.info("k:" + k + ";v:" + v));
    }

    //转换成map,并进行按key排序
    private void test13(List<Student> studentList) {
        log.info("----------------转换成map,并进行按key排序-------------------");
        Map<Integer, Student> studentMap = studentList.stream().collect(Collectors.toMap(Student::getId, Function.identity()));
        log.info("排序前:" + studentMap);
        studentMap = studentMap.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));

        log.info("正序排序后:" + studentMap);
        studentMap = studentMap.entrySet()
                .stream()
                .sorted(Collections.reverseOrder(comparingByKey()))
                .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1));
        log.info("倒序排序后:" + studentMap);
    }

    //对象转换成属性map
    private void test14() {
        List<Student> studentList = Arrays.asList(new Student(1, "张三", 10), new Student(11, "张三2", 10),
                new Student(2, "李四", 20), new Student(3, "李四2", 20), new Student(4, "王五", 30),
                new Student(5, "朱八", 30));
        Map<String, Integer> nameAgeMap = studentList.stream().collect(Collectors.toMap(
                Student::getName,
                Student::getAge
        ));
        log.info("对象转换成属性map:" + nameAgeMap);
    }

    //过滤新数据,对象拷贝,并按年龄分组
    private void test15() {
        List<Student> studentList = Arrays.asList(new Student(1, "张三", 10), new Student(2, "张三2", 10),
                new Student(3, "李四", 15), new Student(4, "李四2", 15), new Student(5, "王五", 29),
                new Student(6, "朱八", 30));
        Map<Integer, List<Student2>> nameAgeMap = studentList.stream().filter(s -> s.getAge() < 30).
                map(s -> BeanUtil.copyProperties(s, Student2.class)).collect(Collectors.groupingBy(Student2::getAge));
        log.info("过滤新数据,对象拷贝,并按年龄分组:" + nameAgeMap);
    }

    //foreach修改
    private void test16(List<Student> studentList) {
        studentList.forEach(s -> s.setName("修改"));
        log.info("修改后的集合:" + studentList);
    }

    //allMatch、noneMatch
    private void test17(List<Student> studentList) {
        log.info("studentList:" + studentList);
        boolean allMatch = studentList.stream().allMatch(s -> s.getAge() >= 10);
        log.info("allMatch:" + allMatch);
        boolean noneMatch = studentList.stream().noneMatch(s -> s.getAge() >= 30);
        log.info("noneMatch:" + noneMatch);
    }

    //Collectors.joining(",")字符串集合以逗号隔开合并成单字符串
    private void test18(List<Student> studentList) {
        log.info("----------------字符串集合以逗号隔开合并成单字符串-------------------");
        String studentNames = studentList.stream().map(Student::getName).collect(Collectors.joining(","));
        log.info("字符串集合以逗号隔开合并成单字符串:" + studentNames);
    }

    //sort 数组排序
    private void test19(List<Student> studentList) {
        log.info("----------------sort 数组排序-------------------");
        List<Student> sortRet = studentList.stream()
                .sorted((student1, student2) -> {
                    int sortBetween = student2.getAge() - student1.getAge();
                    if (sortBetween == 0) {
                        return (student1.getId() - student2.getId()) >= 0 ? -1 : 1;
                    } else {
                        return sortBetween;
                    }
                }).collect(Collectors.toList());
        log.info("sort 倒叙:" + sortRet);
        sortRet = studentList.stream()
                .sorted((student1, student2) -> {
                    int sortBetween = student1.getAge() - student2.getAge();
                    if (sortBetween == 0) {
                        return (student1.getId() - student2.getId()) >= 0 ? 1 : -1;
                    } else {
                        return sortBetween;
                    }
                }).collect(Collectors.toList());
        log.info("sort 正序" + sortRet);
    }

    //按属性分组,并返回指定属性结果集
    private void test20(List<Student> studentList) {
        log.info("----------------按属性分组,并返回指定属性结果集-------------------");
        Map<Integer, List<String>> ageMap = studentList.stream().collect(Collectors.groupingBy(Student::getAge
                , Collectors.mapping(Student::getName, Collectors.toList())));
        log.info("按属性分组,并返回指定属性结果集:" + ageMap);
    }

    //Comparator.comparingInt排序 重新定义排序规则
    private void test21(List<Student> studentList) {
        log.info("----------------Comparator.comparingInt排序 重新定义排序规则------------------");
        Map<Integer, Integer> newSortRole = Maps.newHashMap();
        newSortRole.put(20, 1);
        newSortRole.put(10, 2);
        newSortRole.put(30, 3);
        log.info("Comparator.comparingInt排序前:" + studentList);
        studentList.sort(Comparator.comparingInt(p0 -> newSortRole.get(p0.getAge())));
        log.info("Comparator.comparingInt排序后:" + studentList);
    }
    /**
     * 集合取交集【两个集合同时存在的值】
     */
    private void test22(){
        List<List<Integer>> all=Lists.newArrayList();
        List<Integer> a= Lists.newArrayList(1,2,3,4,5);
        all.add(a);
        List<Integer> b= Lists.newArrayList(1,3,5,7,9);
        all.add(b);
        List<Integer> c= Lists.newArrayList(1,4,5,8,9);
        all.add(c);

        Optional<List<Integer>> result = all.parallelStream()
                .filter(elementList -> elementList != null && elementList.size() != 0)
                .reduce((v1, v2) -> {
                    v1.retainAll(v2);
                    return v1;
                });
        log.info("ret:"+result.get());
        log.info("retainAll:"+a.retainAll(b));
        log.info("a:"+a);
        log.info("retainAll:"+c.retainAll(b));
        log.info("c:"+c);

    }
    /**
     * @description IntStream.rangeClosed 循环指定次数
     * @date 2022/3/11 15:52
     */
    private void test23() {
    List<Student>  student2List=IntStream.rangeClosed(1, 100).mapToObj(s -> Student.builder().age(30 + s).name("张三"+s).build())
            .filter(s -> s.getAge() < 50).collect(Collectors.toList());
    log.info("student2List:{}",student2List);
    }
    /**
     * @description rangeClosed 便捷循环
     * @date 2022/3/18 10:24
     */
    @Test
    public void test24() {
        IntStream.rangeClosed(1,3).forEach(i->{
            log.info("i:{}",i);
        });
        IntStream.range(1,3).forEach(i->{
            log.info("i2:{}",i);
        });
        IntStream.rangeClosed(1,3).parallel().forEach(i->{
            log.info("i3:{}",i);
        });
        String str=IntStream.rangeClosed(1,3).mapToObj(i->"字符串").collect(Collectors.joining("-"));
        log.info("str:{}",str);
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class Student2 {
        private String name;
        private int age;

        @Override
        public String toString() {
            return "Student2{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

3 Optional 用法实例

        //简单字符串的判空
        String name = "张三";
        name = Optional.ofNullable(name).orElse("未设置值");
        log.info("nam:{}", name);
        name = null;
        name = Optional.ofNullable(name).orElse("orElse->未设置值");
        log.info("nam:{}", name);
        name = null;
        name = Optional.ofNullable(name).orElseGet(()-> "orElseGet->未设置值");
        log.info("nam:{}", name);

         //对象判断
        Student student1 = new Student(123, "张三", 30);
        Optional<Integer> optional = Optional.ofNullable(student1).flatMap((e) -> Optional.of(e.getAge()));
        log.info("第一个学生的年龄:" + optional.get());

         name = Optional.ofNullable(student1).map((v) -> v.getName()).get();
        log.info("第一个学生的姓名:" + name);

        Student student2 = new Student(111, null, 30);
        //对象的指定属性为空返回固定值
        String name2 = Optional.ofNullable(student2).map(Student::getName).orElse("员工未注册姓名");
        log.info("第二个学生的名字:" + name2);


        student2 = null;
        Student student3 = new Student(111, "李四", 30);
         //当对象为空直接返回新的对象
        String name3 = Optional.ofNullable(student2).orElseGet(() -> {
            return student3;
        }).getName();
        log.info("第三个学生的名字:" + name3);

       Student student = Optional.ofNullable(student2).orElseThrow(() -> new Throwable("为空直接抛异常"));
        log.info("student:"+student);

ofNullable:不为空往下执行,否则返回null或执行orElseGet或orElse里面的函数或返回值,orElseThrow为空抛异常

输出结果:

INFO:nam:张三
INFO:nam:orElse->未设置值
INFO:nam:orElseGet->未设置值
INFO:第一个学生的年龄:30
INFO:第一个学生的姓名:张三
INFO:第二个学生的名字:员工未注册姓名
INFO:第三个学生的名字:李四

4 Consumer 函数式编程实例

    @Test
    public void test1() {
        List<Student> studentList = Arrays.asList(new Student(0, "张三", 20), new Student(1, "李四", 0));
        myConsumer1(studentList, s -> s.forEach(a ->
                //员工姓名前缀加年份
                a.setName("2021-" + a.getName())));
        log.info("" + studentList);
    }

    public void myConsumer1(List<Student> studentsList, Consumer<List<Student>> consumer) {
        //员工姓名前缀加月份
        studentsList.forEach(s -> s.setName("11 " + s.getName()));
        consumer.accept(studentsList);//回调到调用该方法的地方
    }

输出结果:

[Student(id=0, name=2021-11 张三, age=20), Student(id=1, name=2021-11 李四, age=0)]

5 @FunctionalInterface 函数接口注解

@Slf4j
public class MyFunctionalInterface {

    @Test
    public void test1() {
        Students students = new Students();
        String ret = replacePlaceholders("张三", 20, students::getName);//定义需要传的参数值和函数名称
        log.info("函数式编程返回值:{}",ret);
    }

    public String replacePlaceholders(String name, Integer age, MyFunctionalInterface.PlaceholderResolver placeholderResolver) {
        name=name+"8080【调用函数里面修改】";
        return placeholderResolver.resolvePlaceholder(name, age);
    }
    //被调用的类和方法
    class Students {
        public String getName(String name, Integer age) {
            return "姓名:" + name + ",年龄:" + age ;
        }
    }
    //定义与被调用类绑定接口和接口函数
    @FunctionalInterface
    public interface PlaceholderResolver {
        @Nullable
        String resolvePlaceholder(String name, Integer age);
    }
}

6 Function 函数定义

    @Test
    public void test1(){
        // 先声明方法
        Function<Integer, Integer> funcDouble = (n) -> n * 2;
        Function<Integer, Integer> funcPlus2 = (n) -> n + 2;

        log.info("3*2:"+funcDouble.apply(3));//执行函数->3*2
        log.info("3+2:"+funcPlus2.apply(3));//执行函数->3+2

        log.info("(3*2)+2:"+funcDouble.andThen(funcPlus2).apply(3));// 先执行前面的函数再执行后面的函数->(3*2)+2
        log.info("(3+2)*5:"+funcDouble.compose(funcPlus2).apply(3));// 先执行后面的函数再执行前面的函数->(3+2)*5
        log.info("3*2:"+Function.identity().compose(funcDouble).apply(3));//获取函数定义执行对应的函数->3*2
        log.info("3+2:"+Function.identity().compose(funcPlus2).apply(3));//获取函数定义执行对应的函数->3+2

        //------定义函数并传递函数
        Function<Integer, Student> initStudentFunction=(n)->Student.builder().id(n).build();
        Function<String,String>  addStudentName=(s)->"学生姓名:"+s;
        initStudentInfo(initStudentFunction,addStudentName);
    }

    public void initStudentInfo(Function<Integer, Student> initStudentFunction, Function<String,String>  addStudentName){
        Student student=initStudentFunction.apply(110);
        String name=addStudentName.apply("张三");
        student.setName(name);
        log.info("student:"+student);
    }




    @Test
    public void test2(){
        Function<FutureTaskStudents,String> function=new Function<FutureTaskStudents,String>() {
            @Override
            public String apply(FutureTaskStudents o) {
                return o.getNameAge();
            }
        };
        String ret=getFunctionValue(function,FutureTaskStudents.builder().name("张三").age(100).build());
        System.out.println("ret:"+ret);
    }
    private String getFunctionValue(Function<FutureTaskStudents, String> function, FutureTaskStudents students){
        return function.apply(students);
    }
    @Data
    @Builder
   static class FutureTaskStudents {
        private String name;
        private Integer age;
        public String getNameAge(){
            return this.name+":"+age;
        }
    }
  //两个参数一个返回值
    @Test
    public void test3() {
        BiFunction<String, Integer, String> biFunction = (name, age) -> name + ":" + age;
        String ret = biFunction.apply("张三", 100);
        log.info("ret:{}",ret);
    }

7 Map新语法

   /**
     * computeIfAbsent 获取指定key的值,如果没有这个可以会自动添加此key,list集合直接可以赋值
     * 对指定的可以进行函数式的修改
     */
    @Test
    public void test1(){
        List<String> list=new ArrayList<>();
        Map<String, List> map = Maps.newHashMap();
        list.add("张三");
        list.add("李四");
        map.putIfAbsent("list",list);
        list = map.computeIfAbsent("list", (value) -> new ArrayList<String>());
        log.info("computeIfAbsent list:"+list);//-->{ computeIfAbsent list:[张三, 李四] }

        list = map.computeIfAbsent("list2", (value) -> new ArrayList<String>());
        log.info("computeIfAbsent list2:"+list);
        list.add("World");
        list.add("你好");
        log.info("computeIfAbsent list2:"+list);
        log.info("computeIfAbsent map.:"+map);
        log.info("computeIfAbsent map.values:"+map.values());

        Map<String,String> myMap=new HashMap<>();
        String name=myMap.computeIfPresent("name", (key,value) ->value+"="+value+";");
        log.info("name:"+name);
        myMap.putIfAbsent("name","张三");
         name=myMap.computeIfPresent("name", (key,value) ->key+"="+value+";");
        log.info("name:"+name);//-->{name:name=张三;}
    }
    /**
     * putIfAbsent 不存在指定的key值才会put,避免了多余if判断
     */
    @Test
    public void test2(){
       Map<String,String> map=new HashMap<>();
       map.put("name","张三");
       map.put("name","李四"); //会覆盖前面相同key为name的值
       log.info("map:"+map);
       map.putIfAbsent("name","王五");//假如不存在key为name的键值才会put进去,不然不会
        map.putIfAbsent("age","35");
       log.info("map:"+map);
    }

   8 Predicate/BiPredicate 条件表达式

/**
 * 条件表达式
 */
@Slf4j
public class My_Predicate {
    Predicate<String> predicate1 = myStr ->
            (myStr.startsWith("name") || myStr.contains("张三"));//条件定义,字符串开始为name或包含张三才为TRUE

    
    @Test
    public void test1() {
        check("我的名字是李四", predicate1);
        check("我的名字是张三", predicate1);
        check("张三",30,(name,age)->{
              if (name.equals("张三")&&age==30){
                  return true;
              }else {
                  return false;
              }
        });
    }
   //单参数
    private void check(String myStr, Predicate<String> filter) {
        if (filter.test(myStr)) {
            log.info("字符串'{}'校验通过", myStr);
        } else {
            log.info("字符串'{}'校验不通过", myStr);
        }
    }
   //双参数
    private void check(String name,Integer age, BiPredicate<String,Integer> filter){
        if (filter.test(name,age)){
            log.info("姓名:{},年龄:{} 校验通过",name,age);
        }else {
            log.info("姓名:{},年龄:{} 校验不通过",name,age);
        }

    }

}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值