【Java高级语法】(十五)lambda表达式:给你一颗语法糖Lambda,解析函数式编程的杰作~

Java高级语法详解之lambda表达式

  • 1️⃣ 概念
  • 2️⃣ 优势和缺点
  • 3️⃣ 使用
    • 3.1 语法结构
    • 3.2 案例
      • 3.2.1 无参Lambda
      • 3.2.2 带有一个参数
      • 3.2.3 带有多个参数
      • 3.2.4 方法引用的简化形式
  • 4️⃣ 应用场景
  • 5️⃣ 优化技巧
  • 6️⃣ 原理
  • 7️⃣ 注意性能问题
  • ? 总结

在这里插入图片描述

1️⃣ 概念

Java Lambda表达式是在Java 8中引入的一项重要特性。它们主要受到函数式编程语言的影响,如Haskell和Scala。Lambda表达式为Java引入了一种简洁而强大的功能,可以更便捷地处理函数式编程的概念。

Lambda表达式是一个匿名函数,可以传递给方法作为参数或用作返回值。它是一个使用箭头符号(->)定义的代码块,由Lambda参数、箭头符号和方法体组成。Lambda表达式允许我们将行为作为一等公民进行传递,使得代码更具可读性和灵活性。

2️⃣ 优势和缺点

优点:

  • 简洁性:Lambda表达式允许以更紧凑的方式编写代码,减少样板代码;
  • 使代码更易读:通过使用Lambda表达式,可以将关注点放在实际要执行的操作上,减少了对底层实现的关注;
  • 支持函数式编程风格:能够更好地支持函数式编程的思想,如高阶函数、闭包等。

缺点:

  • 需要理解函数式编程的概念:Lambda表达式需要开发者掌握函数式编程的思想,在初步学习过程中可能较为陌生;
  • 可能引发性能问题:Lambda表达式在某些情况下可能导致额外的开销和性能损失,特别是与传统的循环和条件语句相比。

3️⃣ 使用

3.1 语法结构

Lambda表达式的语法结构如下:

(parameters) -> expression or {statements}

这是最基本的Lambda表达式结构,其中,parameters表示方法参数列表,可以为空或包含一个或多个参数,expression或者{statements}表示要执行的表达式或代码块,用代码块来表示多个语句时,可以在其中包含多条语句并使用return语句返回结果。

而针对不同的情况,Java中Lambda表达式的语法结构有以下几种写法:

  1. 无参情况:当Lambda表达式不需要参数时,可以使用一对空括号代替参数列表,后面可以跟一个表达式或一个代码块。
    () -> expression or {statements}
    
  2. 带有一个参数的情况:当Lambda表达式只有一个参数时,可以省略参数列表的括号。
    parameter -> expression or {statements}
    
  3. 带有多个参数的情况:
    (parameters) -> expression or {statements}
    
  4. 方法引用的简化形式:如果Lambda表达式的主体只是调用一个方法,可以使用方法引用的简化形式来代替具体的Lambda表达式,其中Class是静态方法所在的类名,object是实例方法所在的对象。
    Class::methodName
    object::methodName
    

这些是Lambda表达式的常见写法,在应用程序中根据需求和上下文选择合适的写法。

关于方法引用的知识在后边的文章再具体介绍。

3.2 案例

3.2.1 无参Lambda

public class LambdaExample {
    public static void main(String[] args) {
        // 1. 使用Lambda表达式实现Runnable接口
        Runnable runnable = () -> System.out.println("Hello, World!");
        Thread thread = new Thread(runnable);
        thread.start();
        
        // 2. 使用Lambda表达式实现自定义函数式接口
        MyFunctionalInterface funcInterface = () -> System.out.println("Hello, ChinaAi!");
        funcInterface.run();
    }
}

@FunctionalInterface
interface MyFunctionalInterface {
    void run();
}

在上面代码中,我使用Lambda表达式实现Runnable接口:创建一个Runnable对象,Lambda表达式表示了在run()方法中要执行的代码块。

然后,我使用Lambda表达式实现自定义的函数式接口MyFunctionalInterface:创建一个实现该接口的对象,Lambda表达式表示了在run()方法中要执行的代码块。

运行结果:

Hello, World!
Hello, ChinaAi!

3.2.2 带有一个参数

import java.util.function.Consumer;

public class LambdaExample {
    public static void main(String[] args) {
        // 1. 使用Lambda表达式实现Consumer接口
        Consumer<String> consumer = (name) -> System.out.println("Hello, " + name);
        consumer.accept("Alice");
        
        // 2. 使用Lambda表达式实现自定义函数式接口
        MyFunctionalInterface funcInterface = (name) -> System.out.println("Hello, " + name);
        funcInterface.run("Bob");
    }
}

@FunctionalInterface
interface MyFunctionalInterface {
    void run(String name);
}

在上面代码中,我使用Lambda表达式实现Consumer接口:创建一个Consumer对象,Lambda表达式表示了在accept()方法中要执行的代码块。

然后,我使用Lambda表达式实现自定义的函数式接口MyFunctionalInterface:创建一个实现该接口的对象,Lambda表达式表示了在run(String name)方法中要执行的代码块。

运行结果:

Hello, Alice
Hello, Bob

3.2.3 带有多个参数

import java.util.Comparator;

public class LambdaExample {
    public static void main(String[] args) {
        // 1. 使用Lambda表达式实现Comparator接口
        Comparator<Integer> comparator = (num1, num2) -> Integer.compare(num1, num2);
        int result = comparator.compare(5, 3);
        System.out.println(result);
        
        // 2. 使用Lambda表达式实现自定义函数式接口
        MyFunctionalInterface funcInterface = (num1, num2) -> System.out.println("Sum: " + (num1 + num2));
        funcInterface.run(10, 20);
    }
}

@FunctionalInterface
interface MyFunctionalInterface {
    void run(int num1, int num2);
}

在上面代码中,我使用Lambda表达式实现Comparator接口:创建一个Comparator对象,Lambda表达式表示了在compare(num1, num2)方法中要执行的代码块。其中,调用了静态方法Integer.compare()来比较两个整数的大小。

然后使用Lambda表达式实现自定义的函数式接口MyFunctionalInterface:创建一个实现该接口的对象,Lambda表达式表示了在run(int num1, int num2)方法中要执行的代码块。

运行结果:

1
Sum: 30

3.2.4 方法引用的简化形式

import java.util.function.Consumer;
import java.util.function.Supplier;

public class LambdaExample {
    public static void main(String[] args) {
        // 1. 对象::实例方法
        Consumer<String> consumer1 = System.out::println;
        consumer1.accept("Hello, World!");
        
        // 2. 类名::静态方法
        Supplier<Double> supplier = Math::random;
        double randomNum = supplier.get();
        System.out.println(randomNum);
       
    }
}

在上面代码中,我使用 对象::实例方法 来创建一个Consumer对象,使用对象引用方法的简化形式来执行accept()方法。
使用 类名::静态方法 来创建一个Supplier对象,使用类名引用静态方法的简化形式来执行get()方法。

运行结果:

Hello, World!
0.6158534899118129

4️⃣ 应用场景

Lambda表达式在多种场景下都能发挥作用,包括但不限于:

  • 函数式接口(Functional Interface):通过Lambda表达式可以实现函数式接口的匿名内部类替代;
  • 集合操作:使用Lambda表达式可以在集合上进行筛选、映射、归约等操作,让代码更加简洁和易读;
  • 多线程编程:使用Lambda表达式可以方便地实现多线程任务的并行处理;
  • GUI事件处理:Lambda表达式可以简化GUI应用程序中的事件处理代码。

5️⃣ 优化技巧

在编写和使用Lambda表达式时,可以考虑以下优化技巧:

  • 避免过度复杂化:尽量保持Lambda表达式简洁,以提高代码可读性。
  • 使用方法引用:当Lambda表达式仅仅是调用一个已经存在的方法时,可以使用方法引用来代替,使得代码更加简洁。
  • 多线程优化:结合并行流(parallel stream)和Lambda表达式,可以实现多核处理器的并行计算,提高效率。

6️⃣ 原理

Java语言中的lambda表达式是一种闭包(Closure)的实现方式,它允许我们将函数作为参数传递给其他方法,并且能够在需要的时候延迟执行这些代码。

Lambda表达式最初在Java 8中引入,主要用于简化匿名内部类的编写,使得代码更加简洁、易读。Lambda表达式被视为一种可传递的代码块,充当了函数式接口的一个实例。

Lambda表达式的原理基于如下几个关键概念:

  1. 函数式接口:Lambda表达式的类型由目标上下文推断得出,并且该上下文必须是函数式接口。函数式接口是只包含一个抽象方法的接口。
  2. Lambda表达式语法:Lambda表达式可以通过箭头符号(->)来定义,左侧表示输入参数,右侧表示方法体。例如:(参数) -> { 方法体 }
  3. 类型推断:Java编译器使用目标上下文,根据参数类型进行类型推断,以确定Lambda表达式的类型。
  4. 闭包与捕获变量:Lambda表达式可以访问其周围的局部变量和参数,甚至可以访问final或事实上是final的变量。这些被访问的变量称为捕获变量,并且它们会在形成闭包时被复制。

当使用Lambda表达式时,编译器将根据语法规则将其转化为对应的函数式接口实例。在运行时,可以像传递常规对象一样传递和执行Lambda表达式。这种方式使得我们可以更方便地使用函数式编程风格来处理集合、并发等问题。

7️⃣ 注意性能问题

Java中的lambda表达式在某些情况下可能导致性能问题。以下是几种可能的情况:

  1. 过多的自动装箱和拆箱:Lambda表达式中的参数和返回值类型是通过自动装箱和拆箱来实现的。如果在频繁调用的场景中使用Lambda表达式,会产生大量的对象创建和销毁操作,从而引起性能问题。

  2. 频繁创建匿名内部类:每次使用Lambda表达式时,都会创建一个匿名内部类的实例。如果在循环或高并发应用中频繁创建大量的匿名内部类实例,会导致不必要的开销,影响性能。

  3. 循环中的Lambda表达式:如果在循环中使用Lambda表达式,每次迭代都会创建一个新的Lambda实例。对于大型循环,特别是多层嵌套的循环,这可能导致频繁的垃圾回收和额外的开销,降低性能。

  4. Lambda表达式的逻辑复杂臃肿:如果Lambda表达式内部包含大量的复杂逻辑操作,例如循环、条件判断等,可能会导致Lambda执行时的时间复杂度增加,从而降低性能。

为了避免上述问题,可以采取以下对应策略:

  • 避免在性能敏感的代码块中过度使用Lambda表达式,尤其是频繁调用的地方。
  • 尽量重复使用Lambda实例,避免频繁创建匿名内部类。
  • 对于循环内的Lambda表达式,可以考虑将其提取到循环外部,以减少实例的创建次数。
  • 简化并优化Lambda表达式的逻辑,减少复杂度和执行时间。

同时,最重要的是需要根据具体场景和性能需求评估使用Lambda表达式可能带来的性能影响,并进行必要的优化措施。

? 总结

Java Lambda表达式为Java 8引入了强大的功能,通过简洁的语法使开发者能够更高效地编写代码。无论是在集合操作、多线程编程还是GUI事件处理中,都可以灵活应用Lambda表达式。但需要注意的是,在某些情况下它们可能导致性能问题,因此需要谨慎使用。

在这里插入图片描述文章来源地址https://uudwc.com/A/wJBZZ

原文地址:https://blog.csdn.net/LVSONGTAO1225/article/details/131366787

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年06月25日 13:21
科技项目验收测试规范有哪些?
下一篇 2023年06月25日 13:21