Java 函数式编程 - Lambda 表达式

Java 函数式编程 - Lambda 表达式

Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
Lambda 表达式其实是实现函数式接口的一种语法糖。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。

语法

(parameters) -> expression

(parameters) ->{ statements; }

以下是 lambda 表达式的重要特征:

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

示例

// 随机数生成函数
Supplier<Double> supplier = () -> Math.random();

// 偶数判断函数
Predicate<Integer> predicate = num -> num % 2 == 0;

// 字符串打印函数
Consumer<String> consumer = str -> System.out.println(str);

// 整数转字符串函数
Function<Integer, String> function = num -> String.valueOf(num);

// 整数相加函数
BiFunction<Integer, Integer, Integer> biFunction = (a, b) -> a + b;
// 等效,显式定义参数类型
BiFunction<Integer, Integer, Integer> biFunction2 = (Integer a, Integer b) -> a + b;
// 等效,有大括号
BiFunction<Integer, Integer, Integer> biFunction3 = (a, b) -> {
    return a + b;
};

匿名内部类的等效写法

// 随机数生成函数
Supplier<Double> s1 = () -> Math.random();
// 等效
Supplier<Double> s2 = new Supplier<Double>() {
    @Override
    public Double get() {
        return Math.random();
    }
};

用例

一个简单计算器例子

public class LambdaUsage {

    // 操作符 -> 计算函数
    private static final Map<String, BiFunction<Double, Double, Double>> operationMap = initOperationMap();

    private static Map<String, BiFunction<Double, Double, Double>> initOperationMap() {
        Map<String, BiFunction<Double, Double, Double>> map = new HashMap<>();
        map.put("+", (a, b) -> a + b);
        map.put("-", (a, b) -> a - b);
        map.put("*", (a, b) -> a * b);
        map.put("/", (a, b) -> a / b);
        return map;
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        while (true) {
            double num1 = input.nextDouble();
            String operator = input.next();
            double num2 = input.nextDouble();

            BiFunction<Double, Double, Double> operation = operationMap.get(operator);
            if (operation == null) {
                System.err.println("未知的操作符");
                continue;
            }

            calculate(num1, num2, operation);
        }
    }

    /**
     * 执行计算操作
     *
     * @param num1      操作数1
     * @param num2      操作数2
     * @param operation 操作函数
     */
    private static void calculate(double num1, double num2, BiFunction<Double, Double, Double> operation) {
        Double result = operation.apply(num1, num2);
        System.out.println("结果:" + result);
    }
}
1 + 2
结果:3.0
8 - 5
结果:3.0
2 * 45
结果:90.0
75 / 15
结果:5.0

方法引用

方法引用是 Lambda 表达式的一种语法糖,有以下几种类型:

对象::实例方法

将 lambda 的参数当做方法的参数使用

objectName::instanceMethod

示例:

Consumer<String> c1 = System.out::println;
// 等效
Consumer<String> c2 = (x) -> System.out.println(x);

类::静态方法

将 lambda 的参数当做方法的参数使用

ClassName::staticMethod

示例:

Function<Integer, String> f1 = String::valueOf;
// 等效
Function<Integer, String> f2 = (x) -> String.valueOf(x);

类::实例方法

将 lambda 的第一个参数当做方法的调用者,其他的参数作为方法的参数

ClassName::instanceMethod

示例:

BiPredicate<String, String> p1 = String::equals;
// 等效
BiPredicate<String, String> p2 = (x, y) -> x.equals(y);

构造函数

ClassName::new

示例:

// 无参构造函数
Supplier<User> s1 = User::new;
// 等效
Supplier<User> s2 = () -> new User();

// 有参构造函数
Function<Integer, User> f1 = User::new;
// 等效
Function<Integer, User> f2 = id -> new User(id);

// 创建数组
IntFunction<int[]> s3 = int[]::new;
// 等效
IntFunction<int[]> s4 = size -> new int[size];

参考

posted @ 2021-12-20 16:21  风飞飘杨  阅读(368)  评论(0)    收藏  举报