java中lambda接口一览

1、java中标准定义的用于操作数据的lambda接口都在 package java.util.function; 这个包里面,这些接口都不是用来给你在别的类里面实现的,虽然实现了也没什么关系。

2、lambda的写法实际上是逆反面向对象编程这种思想的,因为在编程中它直接提现了数据的处理的逻辑。

之所有多数语言支持还要有这个功能,我想一方面不管什么样的规范,过于彻底的遵循反而不美,毕竟语言作为工具而言,能打最为重要。

而且在很多的数据分析和处理的代码模块中,这种写法确实很香。

3、lambda最基本的四件套:

接口名 描述  方法
Supplier 提供者,用来返回数据  
Consumer 消费者,用来传入数据  
Predicate 断言或者说判断  
Function 功能或者对数据的操作组装等等  

 

基于这四个接口,java实现了自己的一套操作数据的功能,比如stream里面那些方法,我们也可以基于这四个接口实现自己的一套数据处理流程。

那我们写一个实际的例子,现在有五个人的姓名和身份证号,要按计算他们年龄并且从小到大排序,未满18岁的和大于35岁的我们不要。

解决:我们先构造一个Person类:

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Person {
    private String name;
    private String identifyCardNum;

    private int age;
}

使用上面四个基础lambda接口解决这个问题:

package com.local.lambda;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class Main {

    public static Map<String, Object> buildMap(String name, String identifyCardNum) {
        Supplier<Map<String, Object>> supplier = HashMap::new;
        Map<String, Object> map = supplier.get();
        map.put("name", name);
        map.put("identifyCardNum", identifyCardNum);
        return map;
    }

    public static void main(String[] args) {

        List<Map<String, Object>> personMapList = new ArrayList<Map<String, Object>>() {{
            add(buildMap("张三", "32108119850606"));

            add(buildMap("李四", "32108119980806"));

            add(buildMap("王五", "32108120011006"));

            add(buildMap("钱六", "32108120031206"));

            add(buildMap("孙七", "32108120091206"));
        }};

        List<Person> compose = compose(personMapList, pmList -> {
            List<Person> personList = new ArrayList<>();
            for (Map<String, Object> map : pmList) {
                Person person = new Person();
                int age = calcAge((String) map.get("identifyCardNum"));
                person.setAge(age);
                person.setName((String) map.get("name"));
                
                if(age >= 35 || age <= 18) {
                    continue;
                }
                
                personList.add(person);
            }
            return personList;
        });

        Comparator<Person> comparator = Comparator.comparingInt(Person::getAge);
        compose.sort(comparator);

        printPersonList(compose);
    }

    static List<Person> compose(List<Map<String, Object>> personMapList, Function<List<Map<String, Object>>, List<Person>> composeFun) {
        return composeFun.apply(personMapList);
    }

    /**
     * 打印结果
     * @param personList
     */
    static void printPersonList(List<Person> personList) {
        Consumer<Person> consumer = p -> {
            System.out.println("[" +
                    "name: " + p.getName() + ","
                    + "age: " + p.getAge()
                    + "]");
        };
        for(Person person : personList) {
            consumer.accept(person);
        }
    }

    private static int calcAge(String identifyCardNum) {
        Predicate<String> emptyPredicate = s -> s == null || "".equals(s);
        Predicate<String> acceptablePredicate = s -> s.length() < 14;

        if(emptyPredicate.and(acceptablePredicate).test(identifyCardNum)) {
            throw new RuntimeException("not a acceptable identifyCardNum");
        }

        Function<String, String> birthNumFun = s -> s.substring(6);

        Function<String, Date> birthNumToDateFun = s -> {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
            Date parse = null;
            try {
                parse = simpleDateFormat.parse(s);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return parse;
        };

        Function<Date, Integer> calAgeFun = d -> {
            Calendar birthCal =  Calendar.getInstance();
            birthCal.setTime(d);

            Calendar nowCal =  Calendar.getInstance();
            nowCal.setTime(new Date());

            long diffInMillis = nowCal.getTimeInMillis() - birthCal.getTimeInMillis();
            long diffInDays = TimeUnit.DAYS.convert(diffInMillis, TimeUnit.MILLISECONDS);

            return (int) diffInDays / 365;
        };

        return birthNumFun.andThen(birthNumToDateFun).andThen(calAgeFun).apply(identifyCardNum);
    }

}

 结果:

[name: 钱六,age: 19]
[name: 王五,age: 21]
[name: 李四,age: 24]

Process finished with exit code 0

 

 

PS:

1、Function接口中的compose和andThen区别:

compose先执行调用链右侧逻辑,再执行左侧逻辑;

andThen先执行左侧逻辑,再执行右侧逻辑;

最好别混用。

 

2、通常Consumer可以用来定义自己的增强for循环方法,Supplier则是构建者和工厂模式中用的多,还是蛮好用的。

因为有些大公司是有代码的sonar检查和人工复审的。new和for循环嵌套都会被检测为糟糕代码,这俩东西相当实用!

posted @ 2023-06-12 00:43  时间羚羊  阅读(97)  评论(0编辑  收藏  举报