Java8函数式编程之Lambda表达式

简介: 笔记

一、Lambda表达式简介


函数式编程是种编程范式,它将计算机运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus)。而且λ演 算的函数可以接受函数当作输入(参数)和输出(返回值)。和指令式编程相比,函数式编程强调函数的计算比指令的执行重 要。和过程化编程相比,函数式编程里,函数的计算可随时调用。


(1)示例

为了理解Lambda表达式的概念,下面先从一个示例开始。

假设有这样的一个需求:设计一个通用方法,能够实现两个数值的加法和减法运算。Java中方法不能 单独存在,必须定义在类或接口中,考虑是一个通用方法,可以设计一个数值计算接口,其中定义该 通用方法,代码如下:

//可计算接口
public interface Calculable {
//    计算两个int值
    int calculateInt(int a, int b);
    /**
     * 通过操作符进行计算
     * @param opr 操作符
     * @return 实现 Calculable接口对象
     */
    public static Calculable calculable(char opr){
        Calculable result;
        if (opr == '+'){
//            匿名内部类实现Calculable接口
            result = new Calculable() {
//                实现加法运算
                @Override
                public int calculateInt(int a, int b) {
                    return a+b;
                }
            };
        }else{
//            内部类实现Calculable接口
            result = new Calculable() {
                @Override
                public int calculateInt(int a, int b) {
                    return a-b;
                }
            };
        }
        return result;
    }
}

调用通用方法代码如下:

//测试代码
public class HelloWorld {
    public static void main(String[] args) {
        int n1 = 10;
        int n2 = 5;
//        实现加法计算Calculable对象
        Calculable c1 = Calculable.calculable('+');
        //        实现减法计算Calculable对象
        Calculable c2 = Calculable.calculable('-');
//        调用calculateInt方法进行计算
        System.out.printf("%d + %d=%d \n",n1,n2, c1.calculateInt(n1,n2));
        //        调用calculateInt方法进行计算
        System.out.printf("%d - %d=%d \n",n1,n2,c2.calculateInt(n1,n2));
    }
}


(2)Lambda表达式实现

通过匿名内部类实现通用方法calculate代码很臃肿,Java 8采用Lambda表达式可以替代匿名内

部类。修改之后的通用方法calculate代码如下:

//可计算接口
@FunctionalInterface
public interface Calculable {
//    计算两个int值
    int calculateInt(int a, int b);
    /**
     * 通过操作符进行计算
     * @param opr 操作符
     * @return 实现 Calculable接口对象
     */
    public static Calculable calculable(char opr){
        Calculable result;
        if (opr == '+'){
//            Lambda表达式实现Calculable接口
            result = (int a, int b) ->{
                return a+b;
            };
        }else{
//            Lambda表达式实现Calculable接口
            result = (int a, int b) ->{
                return a-b;
            };
        }
        return result;
    }
}


二、Lambda表达式简化形式


使用Lambda表达式是为了简化程序代码,Lambda表达式本身也提供了多种简化形式,这些简化形式虽然简化了代码,但客观上使得代码可读性变差。

(1)省略参数类型

//可计算接口
@FunctionalInterface
public interface Calculable {
//    计算两个int值
    int calculateInt(int a, int b);
    /**
     * 通过操作符进行计算
     * @param opr 操作符
     * @return 实现 Calculable接口对象
     */
    public static Calculable calculable(char opr){
        Calculable result;
        if (opr == '+'){
//            Lambda表达式实现Calculable接口
            result = ( a,  b) ->{
                return a+b;
            };
        }else{
//            Lambda表达式实现Calculable接口
            result = ( a, b) ->{
                return a-b;
            };
        }
        return result;
    }
}


(2)省略参数小括号

Lambda表达式中参数只有一个时,可以省略参数小括号。


(3)省略return和大括号

如果Lambda表达式体中只有一条语句,那么可以省略return和大括号,代码如下:

public static Calculable calculate(int power) {
    Calculable result;
  if (power == 2) {
// Lambda表达式实现Calculable接口 
    result = (int a) -> { //标准形式
            return a * a;
        };
  } else {
// Lambda表达式实现Calculable接口
    result = a -> a * a * a; //省略形式 1
  };
    return result;
}


三、作为参数使用Lambda表达式


Lambda表达式一种常见的用途是作为参数传递给方法。这需要声明参数的类型声明为函数式接口类型。

代码如下:

public class HelloWorld1 {
    public static void main(String[] args) {
        int n1 = 10;
        int n2 = 5;
        // 打印计算结果加法计算结果
        diaplay((a,b)->{
            return a+b;
        },n1,n2);
        // 打印计算结果减法计算结果
        diaplay((a,b)->a-b,n1,n2);
    }
/**
 * 打印计算结果 *
 * @param calc Lambda表达式
 * @param n1 操作数1
 * @param n2 操作数2 */
    public static void diaplay(Calculable calc,int n1,int n2){
        System.out.println(calc.calculateInt(n1,n2));
    }
}

参数calc类型是Calculable,这个参数即可以接收 实现Calculable接口的对象,也可以接收Lambda表达式,因为Calculable是函数式接口。


四、访问变量


Lambda表达式可以访问所在外层作用域内定义的变量,包括:成员变量和局部变量。


(1)访问成员变量

成员变量包括:实例成员变量和静态成员变量。在Lambda表达式中可以访问这些成员变量,此时的Lambda表达式与普通方法一样,可以读取成员变量,也可以修改成员变量。

public class LambdaDemo {
    // 实例成员变量
    private int value = 10;
    // 静态成员变量
    private static int staticValue = 5;
    // 静态方法,进行加法运算
    public static Calculable add() {
        Calculable result = (int a, int b) -> {
            // 访问静态成员变量,不能访问实例成员变量
            staticValue++;
            int c = a + b +staticValue;
            return c;
        };
        return result;
    }
    // 实例方法,进行减法运算
    public Calculable sub() {
        Calculable result = (int a, int b) -> {
            // 访问静态成员变量和实例成员变量
            staticValue++;
            this.value++;
            int c = a - b - staticValue - this.value;
            return c; 
        };
        return result;
    }
}


(2)捕获局部变量

对于成员变量的访问Lambda表达式与普通方法没有区别,但是对于访问外层局部变量时,会发生“捕 获变量”情况。Lambda表达式中捕获变量时,会将变量当成final的,在Lambda表达式中不能修改那些捕获的变量。 示例代码如下:

public class LambdaDemo {
    // 实例成员变量
    private int value = 10;
    // 静态成员变量
    private static int staticValue = 5;
    // 静态方法,进行加法运算
    public static Calculable add() {
    //局部变量
    int localValue = 20;
        Calculable result = (int a, int b) -> {
            int c = a + b +staticValue;
            return c;
        };
        return result;
    }
    // 实例方法,进行减法运算
    public Calculable sub() {
      //final局部变量
    final int localValue = 20;
        Calculable result = (int a, int b) -> {
            // 访问静态成员变量和实例成员变量
      staticValue++;
      this.value++;
            int c = a - b - staticValue - this.value;
            return c;
        };
        return result;
    }
}


五、方法引用


Java 8之后增加了双冒号“::”运算符,该运算符用于“方法引用”,注意不是调用方法。“方法引用”虽然没有直接使用Lambda表达式,但也与Lambda表达式有关,与函数式接口有关。 方法引用分为:静态方法的方法引用和实例方法的方法引用。它们的语法形式如下:

类型名::静态方法 // 静态方法的方法引用 
实例名::实例方法 // 实例方法的方法引用


被引用方法的参数列表和返回值类型,必须与函数式接口方法参数列表和方法返回值类型 一致。

代码如下:

public class LambdaDemo {
    // 静态方法,进行加法运算
// 参数列表要与函数式接口方法calculateInt(int a, int b)兼容
    public static int add(int a, int b){
        return a + b;
    }
    // 实例方法,进行减法运算
// 参数列表要与函数式接口方法calculateInt(int a, int b)兼容
    public int sub(int a, int b) {
        return a - b;
    }
}

LambdaDemo类中提供了一个静态方法add,一个实例方法sub。这两个方法必须与函数式接口方法参数 列表一致,方法返回值类型也要保持一致。

代码如下:

public class HelloWorld {
    public static void main(String[] args) {
        int n1 = 10;
        int n2 = 5;
        // 打印计算结果加法计算结果
        display(LambdaDemo::add, n1, n2);
        LambdaDemo d = new LambdaDemo();
        // 打印计算结果减法计算结果
        display(d::sub, n1, n2);
    }
    /**
     * 打印计算结果
     * @param calc Lambda表达式 * @param n1 操作数1
     * @param n2 操作数2
     */
    public static void display(Calculable calc, int n1, int n2) {
        System.out.println(calc.calculateInt(n1, n2));
    }
}



相关文章
|
4天前
|
Java API
Java 8新特性之Lambda表达式与Stream API
【5月更文挑战第17天】本文将介绍Java 8中的两个重要特性:Lambda表达式和Stream API。Lambda表达式是一种新的编程语法,它允许我们将函数作为参数传递给其他方法,从而使代码更加简洁。Stream API是一种用于处理集合的新工具,它提供了一种高效且易于使用的方式来处理数据。通过结合使用这两个特性,我们可以编写出更加简洁、高效的Java代码。
13 0
|
6天前
|
Java 开发者
Java一分钟之-Lambda表达式与函数式接口
【5月更文挑战第12天】Java 8引入的Lambda表达式简化了函数式编程,与函数式接口结合,实现了代码高效编写。本文介绍了Lambda的基本语法,如参数列表、箭头符号和函数体,并展示了如何使用Lambda实现`Runnable`接口。函数式接口仅有一个抽象方法,可与Lambda搭配使用。`@FunctionalInterface`注解用于确保接口具有单一抽象方法。文章还讨论了常见的问题和易错点,如非函数式接口、类型冲突以及Lambda表达式的局部变量可见性,并提供了避免这些问题的策略。通过理解Lambda和函数式接口,开发者能提高代码可读性和效率。
44 4
|
1天前
|
Java API
Java 8新特性之Lambda表达式
【5月更文挑战第20天】本文将介绍Java 8中的一个重要特性——Lambda表达式。Lambda表达式是Java 8引入的一种新的编程语法,它允许我们将函数作为参数传递给方法,从而实现更加简洁、灵活的代码。本文将从Lambda表达式的基本概念、语法、使用方法以及优缺点等方面进行详细介绍,帮助读者更好地理解和应用Lambda表达式。
|
4天前
|
移动开发 搜索推荐 Java
Java如何支持函数式编程?,作为移动开发程序员应该怎样去规划自己的学习路线
Java如何支持函数式编程?,作为移动开发程序员应该怎样去规划自己的学习路线
|
6天前
|
Java API
Java 8新特性之Lambda表达式与Stream API实践指南
【5月更文挑战第15天】 随着Java语言的不断发展,Java 8作为一个重要的版本,引入了许多令人兴奋的新特性。其中,Lambda表达式和Stream API是Java 8最受关注的两个特性。本文将深入探讨Lambda表达式的基本概念、语法和使用场景,以及如何结合Stream API实现更加简洁、高效的代码编写。通过实例演示,帮助读者快速掌握这两个新特性,提高Java编程能力。
|
6天前
|
Java API 容器
Java8函数式编程接口:Consumer、Supplier、Function、Predicate
Java8函数式编程接口:Consumer、Supplier、Function、Predicate
8 1
|
6天前
|
Java
Java正则表达式去掉非汉字字符
【5月更文挑战第11天】Java正则表达式去掉非汉字字符
18 3
|
6天前
|
Java API 开发者
Java中Lambda表达式的深入理解与应用
【5月更文挑战第12天】在Java 8之后,Lambda表达式已经成为了Java开发者必备的技能之一。Lambda表达式以其简洁、灵活的特点,大大提高了编程的效率。本文将深入探讨Lambda表达式的基本概念,语法规则,以及在实际开发中的应用,帮助读者更好地理解和使用Lambda表达式。
|
8月前
|
Java 开发者
使用Java 8的新特性:函数式编程和Lambda表达式
Java 8引入了许多令人激动的新特性,其中最重要的是函数式编程和Lambda表达式。这些功能使得Java代码更简洁、易读和灵活。本文将介绍Java 8中的函数式编程和Lambda表达式的基本概念,并展示如何在实际项目中应用它们。
62 1
|
Java 编译器 程序员
Java函数式编程和Lambda表达式
Java函数式编程和Lambda表达式