Java的函数式编程

2022-12-31 14:18:09 浏览数 (2)

背景

JDK8开始引入的函数式编程,大大降低了Java编码的复杂度。它是一种编程范式,即一切都是数学函数。在Java中,函数式编程与lambda表达式密不可分。本文从最基础的编译原理的Statements && Expressions讲起,一步步带你深入浅出函数式编程。

一、Statements && Expressions

语句一般有表达式语句、声明语句、控制流语句,相当于自然语言中的一个句子,一个语句构成一个完整的执行单元。

表达式是由变量、运算符和方法调用组成的,这些变量、运算符和方法调用是根据语言的语法构造的,其计算结果为单个值。

Statements(语句)

Expressions(表达式)

执行某些操作

计算某个值

print("Hello World")

"Hello World"

return 666;

666

if (condition) {...}

condition

表达式可以是语句的一部分,语句从来不是表达式的一部分;所有表达式都是有类型的。 尽管如此,不同的语言对于这些定义会略有不同。 既然提到了简单的提到了这些概念,那么Blocks一般由0或者多个statements组成,用Java示例如下,

代码语言:javascript复制
public static void main(String[] args) {
    boolean condition = true;
    if (condition) { // begin block 1
        System.out.println("Condition is true.");
    } // end block one
    else { // begin block 2
        System.out.println("Condition is false.");
    } // end block 2
}

二、Lambda与函数式编程

Lambda表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。

Java里,函数不是第一等公民,需要封装到接口里。 从而Java Lambda表达式 --> 内部匿名类。

函数式编程起源于称为函数理论的数学模型和 Lambda 演算中的 lambda。Lambda 表达式利用函数式编程特性。在 Java 中使用 Lambda 最明显的体验是它简化并减少了创建某些构造(例如匿名类)所需的源代码量。

lambda写法上一共两种,如下,经过上一章的铺垫这块大家看起来清晰了吧(手动狗头)。 (parameters) -> expressions 或 (parameters) -> { statements; } 代码示例一:

代码语言:javascript复制
private static void lambda() {
    IntSupplier integerExpression = () -> 5;

    IntSupplier intSupplierStatement = () -> {
        int a = 1;
        int b = 1;
        return a   b;
    };
}

代码实例二:

代码语言:javascript复制
interface MyLambdaInterface {
    void doSomeShit(String string);
}

public static void enact(MyLambdaInterface myLambdaInterface, String string) {
    myLambdaInterface.doSomeShit(string);
}

private static void invoke() {
    enact(string -> System.out.println(string), "Hello World");
}

三、常用的函数式接口

JDK 8 中提供了大量的函数式接口,这些接口定义在java.util.function中,因此我们一般情况下不需再定义自己的接口,同时,各个接口的作用和名字都是相对应的,所以,了解函数式接口的命名模式就是很有必要的了。

较为常见的就这四种,通过简单的代码调用,用法见文识义。

  • Supplier->供应商
  • Consumer->消费者
  • Predicate->断言
  • Function->函数
代码语言:javascript复制
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 常用的函数式接口
 * Supplier->供应商
 * Consumer->消费者
 * Predicate->断言
 * Function->函数
 * 
 * @since 2021-10-22-10:04 AM
 */
class App {
    public static void main(String[] args) {
        // 无输入参数,返回T类型的一个结果。
        // public interface Supplier<T>
        Supplier<String> supplier = () -> "Test supplier";
        supplier.get(); // return String | Test supplier

        // 接受一个T类型的参数,无返回。
        // public interface Consumer<T>
        Consumer<String> consumer = (x) -> {
            System.out.println(x);
        };
        // Consumer<String> consumer = System.out::println;
        consumer.accept("Test consumer"); // void | 控制台打印 "Test consumer"

        // 接受一个T类型的参数,返回布尔值。
        // public interface Predicate<T>
        Predicate<String> predicate = x -> x.contains("predicate");
        predicate.test("Test predicate"); // return boolean | true

        // 接受一个T类型的参数,返回R类型结果。
        // public interface Function<T, R>
        Function<Integer, String> function = x -> "This is Integer:"   x;
        function.apply(100); // return String | "This is Integer:100"
    }
}

小结

Java作为一种通用编程语言,吸收了函数式范式,在函数式编程中,实现一个函数,该函数是不被包含在一个类中的,这也是面对对象和函数式编程的基本区别。

函数式编程语言里也可以有对象,但通常这些对象都是恒定不变的,一般是参数或者返回值。函数式编程语言里没有 for/next 循环,因为这些逻辑意味着有状态的改变。在函数式编程语言里通过递归、把函数当成参数传递的方式实现循环逻辑。

0 人点赞