Function函数式的各种写法

引入

在Java中,函数式接口是只包含一个抽象方法的接口。它们是支持Lambda表达式的基础,因为Lambda表达式需要一个目标类型,这个目标类型必须是一个函数式接口

如果要用Lambda表达式,则左边必须对应着一个类型,而这个类型,一定是函数式接口

如:MyFunctionalInterface myFunction = (a,b)->System.out.println(a+b);。这是一个Lambda表达式,而MyFunctionalInterface就是他对应的类型,这个类型一定是函数式接口!

Function,是函数式接口的一个顶层定义。


函数式接口的出入参定义

Java中有非常多的内置FunctionAPI

image-20240115171418929

看起来很多,常用的有按照出入参来分的四个大类一个断言

  1. 有入参,无出参【消费者】:consumer.accept()
    Consumer<String> consumer = (s)->System.out.println("consumer.accept:  " + s);
    consumer.accept("Hello");
    

    执行结果:

    image-20240115172641115

    因为有入参,无出参,所以是消费掉参数。所以内置的方法是void accept(T t),accept翻译过来就是接受的意思,所以我接受一个参数,然后吃掉~不给返回值。

  2. 有入参,有出参【多功能函数】:function.apply()
    Function<String,Integer> function = (s)->Integer.parseInt(s);
    System.out.println("function.apply:  " + function.apply("123"));
    

    执行结果:

    image-20240115172845112

    因为有入参也有出参,所以内置的方法是R apply(T t),apply翻译过来就是应用的意思,我接受你一个参数,去使用它,使用完了之后告诉你结果,给你返回值。

  3. 无入参,无出参【普通函数】
    Runnable runnable = ()->System.out.println("runnable: " + "Hello runnable");
    new Thread(runnable).start();
    

    执行结果:

    image-20240115173155592

  4. 无入参,有出参【提供者】:supplier.get()

    Supplier<String> supplier = ()-> UUID.randomUUID().toString();
    System.out.println("supplier.get:  " + supplier.get());
    

    执行结果:

    image-20240115173425592

    因为没有入参,只有出参,所以内置方法是T get(),get就是拿,你从我这里拿。因为我是提供者,所以我得拿我自己的一个东西,然后分享给你~

  5. 【断言】:Predicate<T>
    Predicate<Integer> predicate = (t)-> t % 2 == 0;
    boolean a = predicate.test(6);  // 正向判断
    boolean b = predicate.negate().test(6); // 反向判断
    System.out.println("predicate.test:  " + a);
    System.out.println("predicate.negate().test:  " + b);
    

    执行结果:

    image-20240116101412445

    boolean test(T t)是正向判断,而negate()是反向判断。

至于其他的内置函数也是同理。比如:

  • BiConsumer的内置方法则是void accept(T t, U u);,bi就是多路的意思,能接受两个入参;
  • DoubleConsumer的内置方法则是void accept(double value);,能接受一个double类型的入参;
  • IntConsumer的内置方法则是void accept(int value);,能接受一个int类型的入参;
  • 其他的内置FunctionAPI亦是同理~

把Function串联起来

知道了有这些内置的接口有什么用呢?怎么把这一系列的操作串联起来呢?

可以看看接下来的这个案例:

        // Supplier 定义数据提供者函数
        Supplier<String> supplier = () -> "42";

        // Predicate 断言:验证是否为一个数字
        Predicate<String> isNumber = s -> s.matches("-?\\d+(\\.\\d)?");

        // Function 转换器:把字符串变成数字
        Function<String,Integer> parseToInt = s -> Integer.parseInt(s);
        // 简化写法  类::实例方法(或静态方法)
        Function<String, Integer> parseToInt2 = Integer::parseInt;

        // Comsumer 消费数据,打印数据
        Consumer<Integer> consumer = num -> {
            if (num % 2 == 0){
                System.out.println(num + "是偶数");
            }else {
                System.out.println(num + "是奇数");
            }
        };

逻辑分解:

  1. Supplier构建一个提供者函数,里面装有一个字符串
  2. Predicate断言,可以判断入参的字符串是不是数字
  3. Function构建转换器,要把入参的字符串转换成数字,然后把数字出参作为出参返回出去
  4. Consumer构建一个消费者函数,把传进来的入参消费掉。不返回出参。

把上面操作串联起来:

        // 串在一起,实现判断42这个字符串是奇数还是偶数
        if (isNumber.test(supplier.get())){
            // 说明是数字
            consumer.accept(parseToInt.apply(supplier.get()));
        }else {
            // 说明不是数字
            System.out.println("非法的数字");
        }

这段代码是不是看起来很乱很复杂?

接下来让我们把代码逻辑一层一层地分解一下:

  1. supplier.get(),这是通过get()方法把Supplier里面的参数拿出来。

  2. isNumber.test(),调用断言的test()方法,判断这个参数是否为数字(正向判断)。

    isNumber.test(supplier.get()),通过断言判断Supplier里的参数是不是数字。如果是:返回true;如果不是:返回false。

    如果Supplier里的参数是数字,则进入到if语句里面。

  3. parseToInt.apply(supplier.get())supplier.get()是一个字符串,parseToInt.apply()的作用就是把这个字符串转成数字

  4. consumer.accept(),接收一个参数,并且内部消费掉,不返回出参。而他的食物,就是前面的parseToInt.apply(supplier.get())

    要接收这个数字,判断他是奇数还是偶数。

例如,

当我的supplier中的字符串是"42"时,

image-20240119174356432

串联起来后输出的是:

image-20240119174316649

而当supplier中的字符串是"42a"时,

image-20240119174423825

串联起来后输出的则是:

image-20240119174433102


以上就是Function函数式的各种写法。这里可能有人会有疑问:

Lambda表达式和Function函数式虽然很简洁,但需要调用多层函数的时候,易读性就会变得非常差。那为什么还要去用呢?为什么还要去学呢?

我个人的见解是:

多层嵌套的时候,代码会变得繁琐,不易于阅读。这也代表着别人维护起来也会变得困难。想一想,如果别人都不熟悉,只有你熟悉的话,这是不是也是一种防御性编程呢~

虽然Lambda表达式和Function函数式多层嵌套会变得繁琐、不利于阅读,

但当一些简单的场景时,利用Lambda表达式看起来会非常的简洁舒服,随之代码也会变得优雅~

创作不易!转载请注明作者及文章链接或作者博客链接——
- 作者:pidanxia
- 链接:https://pidanxia.ink
(链接可为:**文章链接**或者**作者博客链接**)
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇