亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> java

Java Lambda 表达式

Java Lambda 表达式

在本文中,我们将通过示例了解 Java lambda 表达式以及 lambda 表达式与函数式接口、泛型函数式接口和流 API 的使用。

lambda 表达式是在 Java 8 中首次引入的。它的主要目的是增加语言的表达能力。

但是,在进入 lambdas 之前,我们首先需要了解函数式接口。


什么是函数式接口?

如果一个 Java 接口包含一个且只有一个抽象方法,那么它被称为函数式接口。这只有一种方法指定了接口的预期用途。

例如,Runnable java.lang 包中的接口;是一个功能接口,因为它只构成一个方法,即 run() .

示例1:在java中定义一个函数式接口

import java.lang.FunctionalInterface;
@FunctionalInterface
public interface MyInterface{
    // the single abstract method
    double getValue();
}

在上面的例子中,接口 MyInterface 只有一个抽象方法 getValue()。因此,它是一个功能接口。

在这里,我们使用了注解 @FunctionalInterface .注释强制 Java 编译器指示接口是功能接口。因此,不允许有多个抽象方法。不过,这不是强制性的。

在 Java 7 中,函数式接口被视为单一抽象方法或 SAM 类型。在 Java 7 中,SAM 通常使用匿名类实现。

示例 2:在 java 中使用匿名类实现 SAM

public class FunctionInterfaceTest {
    public static void main(String[] args) {

        // anonymous class
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("I just implemented the Runnable Functional Interface.");
            }
        }).start();
    }
}

输出

I just implemented the Runnable Functional Interface.

在这里,我们可以将匿名类传递给方法。这有助于在 Java 7 中编写代码更少的程序。但是,语法仍然很困难,并且需要大量额外的代码行。

Java 8 进一步扩展了 SAM 的功能。由于我们知道函数式接口只有一个方法,因此在将其作为参数传递时不需要定义该方法的名称。 Lambda 表达式让我们能够做到这一点。


lambda 表达式简介

Lambda 表达式本质上是一个匿名或未命名的方法。 lambda 表达式不会自行执行。相反,它用于实现由功能接口定义的方法。

如何在Java中定义lambda表达式?

下面是我们如何在 Java 中定义 lambda 表达式。

(parameter list) -> lambda body

新的运算符(-> ) 被称为箭头运算符或 lambda 运算符。目前语法可能不清楚。让我们探索一些例子,

假设,我们有这样一个方法:

double getPiValue() {
    return 3.1415;
}

我们可以使用 lambda 表达式将这个方法写成:

() -> 3.1415

在这里,该方法没有任何参数。因此,运算符的左侧包含一个空参数。右侧是指定 lambda 表达式操作的 lambda 主体。在这种情况下,它返回值 3.1415。


Lambda 主体的类型

在 Java 中,lambda body 有两种类型。

1。具有单个表达式的主体

() -> System.out.println("Lambdas are great");

这种类型的 lambda 体称为表达式体。

2。由一段代码组成的主体。

() -> {
    double pi = 3.1415;
    return pi;
};

这种类型的 lambda 主体称为块主体。块体允许 lambda 体包含多个语句。这些语句包含在大括号内,您必须在大括号后添加分号。

注意 :对于块体,如果体返回值,可以有一个return语句。但是,表达式主体不需要 return 语句。


示例 3:Lambda 表达式

让我们编写一个使用 lambda 表达式返回 Pi 值的 Java 程序。

如前所述,lambda 表达式不会自行执行。相反,它形成了功能接口定义的抽象方法的实现。

所以,我们需要先定义一个函数式接口。

import java.lang.FunctionalInterface;

// this is functional interface
@FunctionalInterface
interface MyInterface{

    // abstract method
    double getPiValue();
}

public class Main {

    public static void main( String[] args ) {

    // declare a reference to MyInterface
    MyInterface ref;
    
    // lambda expression
    ref = () -> 3.1415;
    
    System.out.println("Value of Pi = " + ref.getPiValue());
    } 
}

输出

Value of Pi = 3.1415

在上面的例子中,


带参数的 Lambda 表达式

到目前为止,我们已经创建了没有任何参数的 lambda 表达式。但是,与方法类似,lambda 表达式也可以有参数。例如,

(n) -> (n%2)==0

这里,括号内的变量 n 是传递给 lambda 表达式的参数。 lambda body 接受参数并检查它是偶数还是奇数。

示例 4:使用带参数的 lambda 表达式

@FunctionalInterface
interface MyInterface {

    // abstract method
    String reverse(String n);
}

public class Main {

    public static void main( String[] args ) {

        // declare a reference to MyInterface
        // assign a lambda expression to the reference
        MyInterface ref = (str) -> {

            String result = "";
            for (int i = str.length()-1; i >= 0 ; i--)
            result += str.charAt(i);
            return result;
        };

        // call the method of the interface
        System.out.println("Lambda reversed = " + ref.reverse("Lambda"));
    }

}

输出

Lambda reversed = adbmaL

通用功能接口

到目前为止,我们已经使用了只接受一种类型值的函数式接口。例如,

@FunctionalInterface
interface MyInterface {
    String reverseString(String n);
}

以上功能接口只接受String 并返回 String .但是,我们可以使功能接口通用,以便接受任何数据类型。如果您不确定泛型,请访问 Java 泛型。

示例 5:通用功能接口和 Lambda 表达式

// GenericInterface.java
@FunctionalInterface
interface GenericInterface<T> {

    // generic method
    T func(T t);
}

// GenericLambda.java
public class Main {

    public static void main( String[] args ) {

        // declare a reference to GenericInterface
        // the GenericInterface operates on String data
        // assign a lambda expression to it
        GenericInterface<String> reverse = (str) -> {

            String result = "";
            for (int i = str.length()-1; i >= 0 ; i--)
            result += str.charAt(i);
            return result;
        };

        System.out.println("Lambda reversed = " + reverse.func("Lambda"));

        // declare another reference to GenericInterface
        // the GenericInterface operates on Integer data
        // assign a lambda expression to it
        GenericInterface<Integer> factorial = (n) -> {

            int result = 1;
            for (int i = 1; i <= n; i++)
            result = i * result;
            return result;
        };

        System.out.println("factorial of 5 = " + factorial.func(5));
    }
}

输出

Lambda reversed = adbmaL
factorial of 5 = 120

在上面的示例中,我们创建了一个名为 GenericInterface 的通用函数接口 .它包含一个名为 func() 的通用方法 .

在这里,在 Main 类中,


Lambda 表达式和流 API

JDK8 中添加了新的 java.util.stream 包,它允许 Java 开发人员执行搜索、过滤、映射、归约等操作或操作 Lists 等集合 .

例如,我们有一个数据流(在我们的例子中是 List String ) 其中每个字符串是国家名称和国家地点的组合。现在,我们可以处理这个数据流并只检索尼泊尔的地点。

为此,我们可以结合 Stream API 和 Lambda 表达式在流中进行批量操作。

示例 6:通过 Stream API 使用 lambda 的演示

import java.util.ArrayList;
import java.util.List;

public class StreamMain {

    // create an object of list using ArrayList
    static List<String> places = new ArrayList<>();

    // preparing our data
    public static List getPlaces(){

        // add places and country to the list
        places.add("Nepal, Kathmandu");
        places.add("Nepal, Pokhara");
        places.add("India, Delhi");
        places.add("USA, New York");
        places.add("Africa, Nigeria");

        return places;
    }

    public static void main( String[] args ) {

        List<String> myPlaces = getPlaces();
        System.out.println("Places from Nepal:");
        
        // Filter places from Nepal
        myPlaces.stream()
                .filter((p) -> p.startsWith("Nepal"))
                .map((p) -> p.toUpperCase())
                .sorted()
                .forEach((p) -> System.out.println(p));
    }

}

输出

Places from Nepal:
NEPAL, KATHMANDU
NEPAL, POKHARA

在上面的例子中,注意语句,

myPlaces.stream()
        .filter((p) -> p.startsWith("Nepal"))
        .map((p) -> p.toUpperCase())
        .sorted()
        .forEach((p) -> System.out.println(p));

在这里,我们使用像 filter() 这样的方法 , map()forEach() 流 API。这些方法可以将 lambda 表达式作为输入。

我们还可以根据上面学到的语法定义自己的表达式。正如我们在上面的示例中看到的那样,这使我们能够大幅减少代码行数。


java

  1. C#接口
  2. Java 运算符
  3. Java 表达式、语句和块
  4. Java 接口
  5. Java try-with-resources
  6. Java 注释
  7. Java NavigableSet 接口
  8. Java中的接口与抽象类:有什么区别?
  9. Java - 正则表达式
  10. Java - 接口
  11. Java 9 - 私有接口方法
  12. Java 8 - Lambda 表达式