Lambda 详解

Lambda 表达式支持将代码块作为方法参数
允许使用更简洁的创建只有一个抽象方法的接口(函数式接口)的实例

来源

lambda 也叫 匿名函数
是从 函数式编程 语言借鉴而来,用于编写清晰,高效的代码

有点像匿名内部类的升级版
相比起来更为简洁。
两者区别在于匿名内部类会创建 class 文件,lambda 只能用于单个抽象方法的接口

java8 的 lambda 引入了两个核心思想

  • 方法引用
  • 行为参数化 把一个方法作为参数传递给另一个方法

入门demon

定义一个处理数组的类,

/**
 * 处理数组的类
 * 这个处理的行为是不确定的
 */
public class ProcessArray {

    /**
     * 只有在调用 process 方法时才知道处理数组的行为
     */
    public void process(int[] target, Command command){
        command.process(target);
    }

}

由于这个行为不固定 我们需要一个 command 接口

/**
 * 命令接口
 */
public interface Command {

    void process(int[] target);

}

我们使用 ProcessArray 这个类需要传入 command 实例, 正常而言会采用匿名内部类的方式

/**
 * 正常采用匿名内部类的方式调用
 */
@Test
public void t1(){
    int[] a = {1,2,3,4};
    ProcessArray processArray = new ProcessArray();
    //调用 process 方法才知道要求和
    processArray.process(a, new Command() {
        @Override
        public void process(int[] target) {
            int sum = 0;
            for (int i : a) {
                sum += i;
            }
            log.info("数组和为{}", sum);
        }
    });
}

lambda 出来后,可以简化一点

/**
 * 通过 lambda 表达式优化代码
 */
@Test
public void t2(){
    int[] a = {1,2,3,4};
    ProcessArray processArray = new ProcessArray();
    processArray.process(a, target -> {
        int sum = 0;
        for (int i : target) {
            sum += i;
        }
        log.info("数组和为{}", sum);
    });
}

以上是 lambda 最简单的应用方式

使用方式

lambda 表达式允许把函数作为一个方法的参数进行传递

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

    public static boolean salutation;

    interface MathOperation{
        int operation(int x,int y);
    };

    int operate(int x, int y,MathOperation mathOperation){
        return mathOperation.operation(x,y);
    }

    @Test
    public void t1(){
        lambdaDemon lambdaDemon = new lambdaDemon();
        MathOperation add = Integer::sum;
        MathOperation division = (x, y) -> x/y;
        System.out.println("10 + 5 = " + lambdaDemon.operate(10, 5, add));
        System.out.println("10 / 5 = " + lambdaDemon.operate(10, 5, division));
    }
}

构造器引用

格式为 ClassName :: new

用处不大 用于调用构造器创建对象
构造器的参数列表 由接口的参数决定
比如 Supplier 接口调用无参构造器 Function 方法可以调用一个参数的构造器

Supplier<String> supply = String::new;
System.out.println(supply.get());

Function<String, String> fun = String::new;
System.out.println(fun.apply("哈哈哈"));

方法引用

是一种语法糖
当 lambda 体中的内容已经有方法实现了,我们可以用方法引用去简化代码
一共有三种语法格式

  • 对象 :: 实例方法名
  • 类 :: 静态方法名
  • 类 :: 实例方法名

对象 :: 实例方法名

    /**
     * 对象 :: 实例方法名
     */
    @Test
    public void t1(){
        //lambda 写法
        Consumer<String> con1 = s -> System.out.println(s);

        //方法引用
        Consumer<String> con2 = System.out::println;
    }

类 :: 静态方法名

    @Test
    public void t2(){
        //lambda 写法
        Comparator<Integer> comparator1 = (x, y)->Integer.compare(x, y);
        System.out.println(comparator1.compare(1, 2));


        //方法引用 ** 需要注意被调用方法的参数列表和返回值类型需要和函数式接口中保持一致 **
        Comparator<Integer> comparator2 = Integer::compare;
    }

类 :: 实例方法名

    @Test
    public void t3(){
        //lambda 写法
        BiPredicate<String, String> biPredicate1 = (x, y) -> x.equals(y);

        //方法引用 ** 第一个参数是这个实例方法的调用者 第二个参数是这个方法的参数时  可以使用这种语法 **
        BiPredicate<String, String> biPredicate2 = String::equals;

    }

版权声明:程序员胖胖胖虎阿 发表于 2022年8月30日 上午7:32。
转载请注明:Lambda 详解 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...