Java Lambda表达式

Lambda表达式

Lambda表达式,也可以称为闭包,是Java 8发布的最重要新特性

  • Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中)
  • 使用Lambda表达式可以使代码变的更加简洁紧凑
  • 语法:
    • (parameter) -> expression
    • (parameter) -> { statement; }
  • parameter: 参数列表,如果只有一个参数,可以省略括号,如果没有参数,也需要使用括号;
  • expression 或 { statement; } 是Lambda表达式的主体

我们可以举一个简单的例子

public class Main {
    public static void main(String[] args) {
//        Lambda表达式计算两数之和
        MathOperation addition = (a, b) -> a + b;
        MathOperation addition2 = (a, b) -> a + b;
        MathOperation addition3 = (a, b) -> a*b;
        System.out.println(addition.operate(5,3));
        System.out.println(addition2.operate(5,3));
        System.out.println(addition3.operate(5,3));

    }
}
interface  MathOperation{
    int operate(int a, int b);
}

在上面的例子中,MathOperation 是一个函数式接口,它包含一个抽象方法 operation,Lambda 表达式(a, b) -> a + b 实现了这个抽象方法,表示对两个参数进行相加操作。

所以,Lambda表达式可以用来实现接口的方法,但是只可以实现一种方法,一种以上如下图

image-20240602223521865

MathOperation operation = (a, b) -> {
            return a / b;
        };
MathOperation operation = (a, b) -> {
            return a * b + 10;
        };

重要特征

简洁性

Lambda 表达式提供了一种更为简洁的语法,尤其适用于函数式接口。相比于传统的匿名内部类,Lambda 表达式使得代码更为紧凑,减少了样板代码的编写。

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

public class Main {
    public static void main(String[] args) {
        //使用匿名内部类
        Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello World!");
            }
        };
        runnable1.run();

// 使用 Lambda 表达式
        Runnable runnable2 = () -> System.out.println("Hello World!");
        runnable2.run();
    }
}

函数式编程支持

Lambda 表达式是函数式编程的一种体现,它允许将函数当作参数传递给方法,或者将函数作为返回值,这种支持使得 Java 在函数式编程方面更为灵活,能够更好地处理集合操作、并行计算等任务

List<String> names = Arrays.asList("Alice","Bob","Cuiweiyang");
names.forEach(name -> System.out.println(name));

实现了一下接口

image-20240602225140382

image-20240602225326647

变量捕获

Lambda 表达式可以访问外部作用域的变量,这种特性称为变量捕获,Lambda 表达式可以隐式地捕获 final 或事实上是 final 的局部变量。

int  x = 10;
Function function = a -> System.out.println(a+x);//注意返回值类型
function.oper(5);
interface Function{
    void oper(int a);
}

方法引用

Lambda 表达式可以通过方法引用进一步简化,方法引用允许你直接引用现有类或对象的方法,而不用编写冗余的代码

// 使用方法引用
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(System.out::println);

可并行性

Lambda 表达式能够更方便地实现并行操作,通过使用 Stream API 结合 Lambda 表达式,可以更容易地实现并行计算,提高程序性能。

// 使用 Lambda 表达式和 Stream API 进行并行计算
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum =numbers.parallelStream().mapToInt(Integer::intValue).sum();
System.out.println("sum: "+sum);

Lambda 表达式的引入使得 Java 编程更加灵活、简洁,并推动了函数式编程的发展。

Lambda表达式实例

Lambda 表达式的简单例子:

// 1. 不需要参数,返回值为 5  
() -> 5  

// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  

// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  

// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  

// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

可以分析一下一下代码

public class Java8Tester {
    public static void main(String []args){
        Java8Tester tester = new Java8Tester();

        // 类型声明
        MathOperation addition = (int a, int b) -> a + b;

        // 不用类型声明
        MathOperation subtraction = (a, b) -> a - b;

        // 大括号中的返回语句
        MathOperation multiplication = (int a, int b) -> { return a * b; };

        // 没有大括号及返回语句
        MathOperation division = (int a, int b) -> a / b;

        System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
        System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
        System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
        System.out.println("10 / 5 = " + tester.operate(10, 5, division));

        // 不用括号
        GreetingService greetService1 = message ->
                System.out.println("Hello " + message);

        // 用括号
        GreetingService greetService2 = (message) ->
                System.out.println("Hello " + message);

        greetService1.sayMessage("Runoob");
        greetService2.sayMessage("Google");
    }

    interface MathOperation {
        int operation(int a, int b);
    }

    interface GreetingService {
        void sayMessage(String message);
    }

    private int operate(int a, int b, MathOperation mathOperation){
        return mathOperation.operation(a, b);
    }
}

使用 Lambda 表达式需要注意以下两点:

  • Lambda 表达式主要用来定义行内执行的方法类型接口(例如,一个简单方法接口)。在上面例子中,我们使用各种类型的 Lambda 表达式来定义 MathOperation 接口的方法,然后我们定义了 operation 的执行。
  • Lambda 表达式免去了使用匿名方法的麻烦,并且给予 Java 简单但是强大的函数化的编程能力

变量作用域

lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。

public class Java8Tester {
   final static String salutation = "Hello! ";
   
   public static void main(String args[]){
      GreetingService greetService1 = message -> 
      System.out.println(salutation + message);
      greetService1.sayMessage("Runoob");
   }
    
   interface GreetingService {
      void sayMessage(String message);
   }
}

$ javac Java8Tester.java
$ java Java8Tester
Hello! Runoob

我们也可以直接在 lambda 表达式中访问外层的局部变量:

public class Java8Tester {
    public static void main(String args[]) {
        final int num = 1;
        Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
        s.convert(2);  // 输出结果为 3
    }
 
    public interface Converter<T1, T2> {
        void convert(int i);
    }
}

lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)

int num = 1;  
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);
num = 5;  
//报错信息:Local variable num defined in an enclosing scope must be final or effectively final

在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。

String first = "";  
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length());  //编译会出错 
posted @   Yang0710  阅读(117)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
  1. 1 イエスタデイ(翻自 Official髭男dism) 茶泡饭,春茶,kobasolo
  2. 2 世间美好与你环环相扣 柏松
世间美好与你环环相扣 - 柏松
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 尹初七

作曲 : 柏松

编曲 : 彭圣杰

偏偏秉烛夜游

偏偏秉烛夜游

午夜星辰 似奔走之友

爱你每个结痂伤口

酿成的陈年烈酒

入喉尚算可口

入喉尚算可口

怎么泪水 还偶尔失守

邀你细看心中缺口

裂缝中留存 温柔

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

知道你不能 还要你感受

知道你不能 还要你感受

让星光加了一点彩虹

让樱花偷偷 吻你额头

让世间美好 与你环环相扣

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

知道你不能 还要你感受

知道你不能 还要你感受

让星光加了一点彩虹

当樱花开的纷纷扬扬

当世间美好 与你环环相扣

特别鸣谢:槿葵,我们的海报制作妹妹。

原唱:柏松

吉他:柏松

和声:柏松

录音:柏松

混音:张强

点击右上角即可分享
微信分享提示