ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Lambda 表达式基础理论与示例

2021-11-01 06:00:06  阅读:237  来源: 互联网

标签:String 示例 int Java8Tester 基础理论 public 表达式 Lambda


Lambda 表达式基础理论与示例

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

Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

使用 Lambda 表达式可以使代码变的更加简洁紧凑。

语法

lambda 表达式的语法格式如下:

(parameters) -> expression

(parameters) ->{ statements; }

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

可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。

可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。

可选的大括号:如果主体包含了一个语句,就不需要使用大括号。

可选的返回关键字:如果主体只有一个表达式返回值,编译器会自动返回值,大括号需要指定表达式返回了一个数值。

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)

在 Java8Tester.java 文件输入以下代码:

Java8Tester.java 文件

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);

   }

}

执行以上脚本,输出结果为:

$ javac Java8Tester.java

$ java Java8Tester

10 + 5 = 15

10 - 5 = 5

10 x 5 = 50

10 / 5 = 2

Hello Runoob

Hello Google

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

Lambda 表达式主要用来定义行内执行的方法类型接口,例如,一个简单方法接口。在上面例子中,使用各种类型的Lambda表达式,定义MathOperation接口的方法。然后定义了sayMessage的执行。

Lambda 表达式免去了使用匿名方法的麻烦,给予Java简单但是强大的函数化的编程能力。

变量作用域

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

在 Java8Tester.java 文件输入以下代码:

Java8Tester.java 文件

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 表达式中访问外层的局部变量:

Java8Tester.java 文件

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());  //编译会出错

 

Java的方法分为实例方法,例如Integer定义的equals()方法:

 

public final class Integer {

    boolean equals(Object o) {

        ...

    }

}

以及静态方法,例如Integer定义的parseInt()方法:

public final class Integer {

    public static int parseInt(String s) {

        ...

    }

}

无论是实例方法,还是静态方法,本质上都相当于过程式语言的函数。例如C函数:

char* strcpy(char* dest, char* src)

只不过Java的实例方法隐含地传入了一个this变量,即实例方法总是有一个隐含参数this。

函数式编程(Functional Programming)是把函数作为基本运算单元,函数可以作为变量,可以接收函数,还可以返回函数。历史上研究函数式编程的理论是Lambda演算,所以经常把支持函数式编程的编码风格称为Lambda表达式。

Lambda表达式

在Java程序中,经常遇到一大堆单方法接口,即一个接口只定义了一个方法:

Comparator

Runnable

Callable

以Comparator为例,想要调用Arrays.sort()时,可以传入一个Comparator实例,以匿名类方式编写如下:

String[] array = ...

Arrays.sort(array, new Comparator<String>() {

    public int compare(String s1, String s2) {

        return s1.compareTo(s2);

    }

});

上述写法非常繁琐。从Java 8开始,可以用Lambda表达式替换单方法接口。改写上述代码如下:

// Lambda

import java.util.Arrays;

public class Main {

    public static void main(String[] args) {

        String[] array = new String[] { "Apple", "Orange", "Banana", "Lemon" };

        Arrays.sort(array, (s1, s2) -> {

            return s1.compareTo(s2);

        });

        System.out.println(String.join(", ", array));

    }

}

 Run

观察Lambda表达式的写法,它只需要写出方法定义:

(s1, s2) -> {

    return s1.compareTo(s2);

}

其中,参数是(s1, s2),参数类型可以省略,因为编译器可以自动推断出String类型。-> { ... }表示方法体,所有代码写在内部即可。Lambda表达式没有class定义,因此写法非常简洁。

如果只有一行return xxx的代码,完全可以用更简单的写法:

 

Arrays.sort(array, (s1, s2) -> s1.compareTo(s2));

返回值的类型也是由编译器自动推断的,这里推断出的返回值是int,因此,只要返回int,编译器就不会报错。

FunctionalInterface

把只定义了单方法的接口称之为FunctionalInterface,用注解@FunctionalInterface标记。例如,Callable接口:

@FunctionalInterface

public interface Callable<V> {

    V call() throws Exception;

}

再来看Comparator接口:

@FunctionalInterface

public interface Comparator<T> {

    int compare(T o1, T o2);

    boolean equals(Object obj);

    default Comparator<T> reversed() {

        return Collections.reverseOrder(this);

    }

    default Comparator<T> thenComparing(Comparator<? super T> other) {

        ...

    }

    ...

}

虽然Comparator接口有很多方法,但只有一个抽象方法int compare(T o1, T o2),其他的方法都是default方法或static方法。另外注意到boolean equals(Object obj)是Object定义的方法,不算在接口方法内。因此,Comparator也是一个Functional Interface。

 

参考链接:

https://www.runoob.com/java/java8-lambda-expressions.html

https://www.liaoxuefeng.com/wiki/1252599548343744/1305158055100449

 

 

标签:String,示例,int,Java8Tester,基础理论,public,表达式,Lambda
来源: https://www.cnblogs.com/wujianming-110117/p/15491870.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有