lambda学习记录

lambda表达式出现之前,我们一般使用匿名内部类来实现。

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("内部类写法");
            }
        }).start();

出现lambda之后的写法:

	new Thread(() -> System.out.println("lambda写法")).start();    

更加的简洁和优雅。

1、语法使用

	(paramters) -> {statements;}  
    展开如:
    (Type1 param1, Type2 param2, Type2 param2, ...) -> {
        statement1;
        statement2;
        statement3;
        ...
        return statementX;
    }

2、语法特征

可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

    //入参为空
    Demo dome = () -> "no param";
    Demo dome2 = () -> { return "no param"; };
    System.out.println(dome.hi());

    //单个参数
    Demo2 dome21 = p -> p;
    Demo2 param22 = p -> { return p;};
    System.out.println(dome21.hei("hello word"));

    //多个参数
    Demo3 more1 = (String hello, String name) -> hello + " " + name;
    //一条返回语句,可以省略大括号和return
    Demo3 more2 = (hello, name) -> hello + name;
    //多条处理语句,需要大括号和return
    Demo3 more3 = (hello, name) -> {
        System.out.println("come...");
        return hello + name;
    };
    System.out.println(more1.greet("hello", "lambda"));

3、方法引用

3.1 对象::实例方法,将lambda的参数当做方法的参数使用

	object::method

例子:

    Consumer<String> sc = System.out::println;
    //等效
    Consumer<String> sc2 = (x) -> System.out.println(x);
    sc.accept("618, 狂欢happy");

3.2 类::静态方法,将lambda的参数当做方法的参数使用

	Class::staticMethod

例子:

    //ClassName::staticMethod  类的静态方法:把表达式的参数值作为staticMethod方法的参数
    Function<Integer, String> sf = String::valueOf;
    //等效
    Function<Integer, String> sf2 = (x) -> String.valueOf(x);
    String apply1 = sf.apply(61888);

3.3 类::实例方法,将lambda的第一个参数当做方法的调用者,其他的参数作为方法的参数。开发中尽量少些此类写法,减少后续维护成本。

Class::instanceMethod

例子:

    //ClassName::instanceMethod  类的实例方法:把表达式的第一个参数当成instanceMethod的调用者,其他参数作为该方法的参数
    BiPredicate<String, String> sbp = String::equals;
    //等效
    BiPredicate<String, String> sbp2 = (x, y) -> x.equals(y);
    boolean test = sbp.test("a", "A");

4、构造函数

类::实例方法
无参例子:

    Supplier<User> us = User::new;
    //等效
    Supplier<User> us2 = () -> new User();
    //获取对象
    User user = us.get();

有参例子:

    //一个参数,参数类型不同则会编译出错
    Function<Integer, User> uf = id -> new User(id);
    //或加括号
    Function<Integer, User> uf2 = (id) -> new User(id);
    //等效
    Function<Integer, User> uf3 = (Integer id) -> new User(id);
    User apply = uf.apply(61888);

    //两个参数
    BiFunction<Integer, String, User> ubf = (id, name) -> new User(id, name);
    User 狂欢happy = ubf.apply(618, "狂欢happy");

5、例子

package lambda;

import org.junit.Test;

public class LambdaTest {

    @Test
    public void domeTest() {
        testVoid(() -> System.out.println("OK"));//传lambda表达式 一个匿名函数对应一个方法
        testReturn(Math::random);
        testVoid(TestLambda::test);//双冒号 即直接传方法参数 方法必须为静态方法
        System.out.println(this.get().invoke(1));
        System.out.println(this.get2().invoke(2));
        System.out.println(this.get3().invoke(3));
    }

    private void testVoid(VoidTest voidTest) {
        voidTest.test();
    }

    private void testReturn(ReturnTest returnTest) {
        System.out.println(returnTest.test());
    }

    private Int2String get() {
        return Object::toString;
    }

    private Int2String get2() {
        return integer -> {
            if (integer % 2 == 0)
                return integer + "是偶数";
            else
                return integer + "是奇数";
        };
    }

    private Int2String get3() {
        return this::i2s;
    }

    private String i2s(Integer s) {
        return "i2s: " + s;
    }

}

class TestLambda {
    static void test() {
        System.out.println("a.f");
    }
}
@FunctionalInterface
interface ReturnTest{
    double test();
}
interface VoidTest {
    void test();
}
@FunctionalInterface
public interface Int2String {
    String invoke(Integer integer);
}

6、什么式函数式接口

  • 只包含一个抽象方法的接口,称为函数式接口
  • 可以在任意函数式接口上使用@FunctionalInterface注解,这样可以检查是否是函数式接口,同时javadoc也会包含一条声明,说明这个接口是函数式接口

自定义函数式接口

@FunctionalInterface
public interface CheckMsgNumber4Biz {
    OpenApiResult<List<MsgNumber>> check(List<MsgNumber> msgNumberList);
}

7、应用场景

函数接口

/**
 * 检查接入号的函数接口
 */
@FunctionalInterface
public interface CheckMsgNumber4Biz {
    OpenApiResult<List<MsgNumber>> check(List<MsgNumber> msgNumberList);
}
    /**
     * 检查接入号,不存在就创建
     *
     * @param msgNumberInfos   传入的接入号对象集合
     * @param customer         租户
     * @param checkMsgNumber4Biz 校验接入号函数,根据不同的业务传入不同函数
     * @return 可用的号码集合,和不可用的错误信息
     */
    public OpenApiResult<List<String>> checkAndSaveMsg(List<MsgNumberInfo> msgNumberInfos,
                                                       Customer customer, CheckMsgNumber4Biz checkMsgNumber4Biz) {
        //可用号码集合
        List<String> usableNumberList = Lists.newArrayList();
        //错误信息
        List<String> errorMsgList = Lists.newArrayList();
        //校验存在
        MsgNumberPacker msgNumberPacker = this.groupMsgNumber(msgNumberInfos);
        //对存在的接入号做校验
        if (CollectionUtils.isNotEmpty(msgNumberPacker.getExistedList())) {
            //校验租户是否匹配
            OpenApiResult<List<MsgNumber>> matchResult =
                    this.matchMsgNumberAndCustomer(msgNumberPacker.getExistedList(), customer);
            OpenApiResult.appendErrorMsg(errorMsgList, matchResult.getErrorMsg()); //追加错误信息
            if (OpenApiResult.isSuccessAndDataNotNull(matchResult)) {
                //校验业务合法性
                OpenApiResult<List<MsgNumber>> checkMsgNumberResult =
                		//***********函数是接口校验***********
                        checkMsgNumber4Biz.check(msgNumberPacker.getExistedList());
                        //***********函数是接口校验***********
                OpenApiResult.appendErrorMsg(errorMsgList, checkMsgNumberResult.getErrorMsg()); //追加错误信息
                if (OpenApiResult.isSuccessAndDataNotNull(checkMsgNumberResult)) {
                    //添加可用号码
                    usableNumberList.addAll(
                            checkMsgNumberResult.getData().stream()
                                    .map(MsgNumber::getMsgNumber).collect(Collectors.toList())
                    );
                }
            }
        }
        //创建不存在的接入号
        if (CollectionUtils.isNotEmpty(msgNumberPacker.getNeedCreateList())) {
            //批量创建
            this.saveMsgNumber(msgNumberPacker.getNeedCreateList(), customer);
            //添加可用号码
            usableNumberList.addAll(msgNumberPacker.getNeedCreateList().stream()
                    .map(MsgNumberInfo::getMsgNumber).collect(Collectors.toList()));
        }
        //返回
        if (CollectionUtils.isEmpty(usableNumberList)) {
            return OpenApiResult.fail(OpenApiResult.Enum.NO_HAVE_USABLE_NUMBER, errorMsgList);
        } else {
            return OpenApiResult.success(usableNumberList, errorMsgList);
        }
    }

业务场景1:

    @Resource(name = "openApiMsgNumberService")
    private OpenApiMsgNumberService openApiMsgNumberService;

    /**
     * 保存
     *
     * @param openOrgQO 保存机构入参对象
     * @param flag      新增标记
     * @return OrgInfo
     */
    @Transactional
    public OpenApiResult<OrgInfo> save(OpenOrgQO openOrgQO, String flag) {
        //检查租户
        OpenApiResult<Customer> checkCustomerResult = openApiCustomerService.checkCustomer(openOrgQO.getCustomerId());
        if (OpenApiResult.isFail(checkCustomerResult)) {
            return OpenApiResult.fail(checkCustomerResult);
        }
        Customer customer = checkCustomerResult.getData();
        //校验机构合法性
        OpenApiResult<?> checkOrgBeforeSave = this.checkOrgBeforeSave(openOrgQO);
        if (OpenApiResult.isSuccess(checkOrgBeforeSave)) {
            //检查、保存接入号
            OpenApiResult<List<String>> checkAndSaveMsgResult =
                    openApiMsgNumberService.checkAndSaveMsg(
                            openOrgQO.getMsgNumberInfos(), customer,
                            //*********此为本业务场景函数接口具体逻辑*********
                             this.getCheckMsgNumber4Biz());
                             //*********此为本业务场景函数接口具体逻辑*********
            if (OpenApiResult.isSuccessAndDataNotNull(checkAndSaveMsgResult)) {
                //封装返回
                return this.saveOrg(openOrgQO, customer, checkAndSaveMsgResult.getData(), flag)
                        //追加errorMsg
                        .appendErrorMsg(checkAndSaveMsgResult.getErrorMsg());
            } else {
                //失败返回
                return OpenApiResult.fail(checkAndSaveMsgResult);
            }
        } else {
            //不合法
            return OpenApiResult.fail(checkOrgBeforeSave);
        }
    }

    /**
     * 获取校验接入号函数接口实现
     * ps:单独抽取出来,以后可能复用。
     *
     * @return CheckMsgFunction
     */
    private CheckMsgNumber4Biz getCheckMsgNumber4Biz() {
        return msgNumbers -> {
            List<MsgNumber> usableMsgNumberList = Lists.newArrayList(); //可用接入号
            List<String> errorMsg = Lists.newArrayList(); //错误信息
            for (MsgNumber msgNumber : msgNumbers) {
                //是否存在机构
                if (msgNumber.getOrgInfo() == null)
                    //不存在机构,可用
                    usableMsgNumberList.add(msgNumber);
                else
                    //存在机构,不可用,加入错误信息
                    errorMsg.add("接入号【" + msgNumber.getMsgNumber() + "】: 已经存在机构,名称【"
                            + msgNumber.getOrgInfo().getOrgName() + "】");
            }
            return OpenApiResult.success(usableMsgNumberList, errorMsg);
        };
    }

业务场景2:

    @Resource(name = "openApiMsgNumberService")
    private OpenApiMsgNumberService openApiMsgNumberService;

    /**
     * 保存菜单
     *
     * @param openMenuQO 入参对象
     * @param flag       操作标记
     * @return Menu
     */
    private OpenApiResult<Menu> checkAndSaveMenu(OpenMenuQO openMenuQO, String flag) {
        //校验租户
        OpenApiResult<Customer> checkCustomerResult =
                openApiCustomerService.checkCustomer(openMenuQO.getCustomerId());
        if (OpenApiResult.isFail(checkCustomerResult)) {
            return OpenApiResult.fail(checkCustomerResult);
        }
        Customer customer = checkCustomerResult.getData();
        //校验菜单
        OpenApiResult<?> checkMenuBeforeSaveResult = this.checkMenuBeforeSave(openMenuQO);
        if (OpenApiResult.isSuccess(checkMenuBeforeSaveResult)) {
            //校验、保存接入号
            OpenApiResult<List<String>> checkAndSaveMsgResult =
                    openApiMsgNumberService.checkAndSaveMsg(
                            openMenuQO.getMsgNumberInfos(), customer, 
                            //*********此为本业务场景函数接口具体逻辑*********
                            this.getCheckMsgFunction());
                            //*********此为本业务场景函数接口具体逻辑*********
            if (OpenApiResult.isSuccessAndDataNotNull(checkAndSaveMsgResult)) {
                //封装返回
                return this.saveMenu(openMenuQO, customer, checkAndSaveMsgResult.getData(), flag)
                        //需要追加的errorMsg
                        .appendErrorMsg(checkAndSaveMsgResult.getErrorMsg());
            } else {
                //失败返回
                return OpenApiResult.fail(checkAndSaveMsgResult);
            }
        } else {
            return OpenApiResult.fail(checkMenuBeforeSaveResult);
        }
    }

    /**
     * 接入号校验函数实现
     *
     * @return CheckMsgFunction
     */
    private CheckMsgNumber4Biz getCheckMsgFunction() {
        //后续需要可以添加控制
        return OpenApiResult::success;
    }

根据以上可以看出,因为在checkAndSaveMsg方法中有检验,但是不同的业务场景的逻辑校验不同,所以可以使用函数式接口。在各自的业务中不同的实现,这样在组件统一调用时会根据不同的业务场景,传入不同的逻辑代码,实现不同的业务逻辑,更加方便快捷。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值