Expresión JavaLambda

1. Primer conocimiento de Lambda

Sabemos que en Java no se puede crear una instancia de una interfaz, pero un objeto de interfaz puede apuntar a su objeto de clase de implementación. ¿Qué sucede si la interfaz ni siquiera tiene un objeto de implementación? Entonces también puede usar clases anónimas, de la siguiente manera:

public class JavaTest {
    
    
    public static void main(String[] args) {
    
    
        Fly fly = new Fly() {
    
    
            @Override
            public void fly(String name) {
    
    
                System.out.println(name + "飞行");
            }
        };
        fly.fly("张三");
    }
}

interface Fly{
    
    
    abstract void fly(String name);
}

Sin embargo, usando el método interno anónimo, la cantidad de código no es muy concisa, y para hacer el código más conciso, Java introduce el método de escritura de expresiones Lambda , a través de una sintaxis más simple, para lograr tales funciones, usando expresiones Lambda para simplificar el código se muestra a continuación:

public class JavaTest {
    
    
    public static void main(String[] args) {
    
    
        Fly fly = name -> System.out.println(name + "飞行");
        fly.fly("张三");
    }
}

interface Fly{
    
    
    abstract void fly(String name);
}

El mismo efecto se logra a través de las expresiones Lambda, pero la cantidad de código se simplifica mucho. Este es el encanto de las expresiones Lambda.

2. Interfaz funcional

Antes de aprender la sintaxis de las expresiones Lambda, primero debe saber qué es una interfaz funcional . Una interfaz con un solo método para implementar se denomina interfaz funcional.

//接口中只有一个待实现的方法 fly,所以这是函数式接口
interface Fly{
    
    
     void fly(String name);
}
//接口中有两个待实现的方法 这是不是函数式接口
interface Run{
    
    
    void fastRun();
    void slowRun();
}
//接口中有两个方法,但其中一个是已经定义好的default方法,真正需要子类去实现的方法只有一个 这是函数式接口
interface Jump{
    
    
    void jump();
    default void highJump(){
    
    
        System.out.println("跳的更高");
    }
}

Puede agregar la anotación **@FunctionalInterface a la interfaz para afirmar que la interfaz es una interfaz funcional. Si la interfaz no es una interfaz funcional, la compilación generará un error.
inserte la descripción de la imagen aquí
¿Por qué deberías saber qué es una interfaz funcional? Debido a que las expresiones lambda simplifican la forma en que una clase anónima implementa una interfaz, solo
puede funcionar en interfaces funcionales**.
Esto es fácil de entender, si una interfaz tiene múltiples métodos para implementar, la expresión lambda no puede decir qué método en la interfaz está implementando ahora.

3. Sintaxis de expresiones lambda

Las expresiones lambda introducen un operador **“->”** en el lenguaje Java, que se denomina operador lambda u operador de flecha. Divide la Lambda en dos partes:

Lado izquierdo: Se especifican todos los parámetros requeridos por la expresión Lambda
. Lado derecho: Se especifica el cuerpo de Lambda, es decir, la función que ejecutará la expresión Lambda.
Me gusta esto:

(parameters) -> expression
或
(parameters) ->{ statements; }

Además de -> y el cuerpo Lambda de las expresiones Lambda, se pueden omitir otros parámetros, paréntesis y corchetes según el tipo de parámetro y el número de líneas de código en el cuerpo del método.
Tomemos como ejemplo la implementación de la siguiente interfaz funcional:

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);
    }
    
    interface NoParam{
    
    
        int returnOne();
    }

Las siguientes son las características importantes de las expresiones lambda:

  • Declaración de tipo opcional : las expresiones lambda no necesitan declarar los tipos de parámetros del método de implementación, y el compilador puede identificar uniformemente los valores de los parámetros.
        // 类型声明
        MathOperation addition = (int a, int b) -> a + b;
        // 不用类型声明
        MathOperation subtraction = (a, b) -> a - b;
  • Paréntesis de parámetros opcionales : un parámetro no necesita definir paréntesis, pero ningún parámetro o múltiples parámetros necesitan definir paréntesis.
      // 不用括号
        GreetingService greetService1 = message ->
                System.out.println("Hello " + message);

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

  • Llaves opcionales : si el cuerpo contiene una declaración, no se requieren llaves.
     // 多条语句不可以省略大括号
        MathOperation multiplication = (int a, int b) -> {
    
    
            int num = a+1;
            num = a + b;
            return a * b + num;
        };

        // 单条语句可以省略大括号
        MathOperation division = (int a, int b) -> a / b;
  • Palabra clave de retorno opcional : si el cuerpo tiene solo un valor de retorno de la expresión, el compilador devolverá automáticamente el valor. Las llaves deben especificar que la expresión devuelve un valor.
  // 多条语句的Lambda表达式如果有返回值,需要使用return
        MathOperation multiplication = (int a, int b) -> {
            int num = a+1;
            num = a + b;
            return a * b + num;
        };

        // 单条语句可以省略return
        MathOperation division = (int a, int b) -> a / b;

En cuarto lugar, el ámbito de uso de las expresiones lambda.

Las expresiones lambda no solo se usan para simplificar la creación de una clase anónima, hay muchos más usos.

1. Asignar un valor a una variable

En lo anterior, el uso de expresiones Lambda es el método de escritura para asignar valores de variables, lo que puede simplificar el segmento de código de la asignación de clase interna anónima y mejorar la eficiencia de lectura.

MathOperation subtraction = (a, b) -> a - b;

2. Como resultado de la devolución

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

    MathOperation getOperation(int a, int b){
    
    
        return (a1, b1) -> a+b;
    }

3, como un elemento de matriz

MathOperation math[] = {
    
    
                (a,b) -> a+b,
                (a,b) -> a-b,
                (a,b) -> a*b
        };

4. Como parámetros de métodos ordinarios o constructores

public static void main(String args[]){
    
    

        Java8Tester java8Tester = new Java8Tester();
        java8Tester.operate(1,2,((a, b) -> a*b));

    }

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

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

Cinco, el alcance de la expresión lambda

Dentro del cuerpo de expresión de una expresión lambda, se puede acceder a las variables fuera del cuerpo de expresión, pero no se pueden modificar otras variables.
inserte la descripción de la imagen aquí

Seis, escritura de referencia de expresión lambda

Al aprender Lambda, también puede encontrar una forma extraña de escribir, como el siguiente código:

// 方法引用写法
GreetingService greetingService = System.out::println;
        greetingService.sayMessage("hello world");

Hay un símbolo nunca antes visto :: , que se llama referencia de método.
Obviamente, usar referencias de métodos es un poco más conciso que las expresiones lambda ordinarias.

Si la implementación de una interfaz funcional se puede lograr llamando a un método , entonces podemos usar referencias de métodos.

public class Java8Tester {
    
    


    public static void main(String args[]){
    
    

        // 静态方法引用--通过类名调用
        GreetingService greetingService = Test::MyNameStatic;
        greetingService.sayMessage("hello");
        Test t = new Test();
        //实例方法引用--通过实例调用
        GreetingService greetingService2 = t::myName;
        // 构造方法方法引用--无参数
        Supplier<Test> supplier = Test::new;
        System.out.println(supplier.get());
    }



    interface GreetingService {
    
    
        void sayMessage(String message);
    }


}

class Test {
    
    
    // 静态方法
    public static void MyNameStatic(String name) {
    
    
        System.out.println(name);
    }

    // 实例方法
    public void myName(String name) {
    
    
        System.out.println(name);
    }

    // 无参构造方法
    public Test() {
    
    
    }
}

7. Ventajas y desventajas de las expresiones Lambda

ventaja:

  • Menos líneas de código : uno de los mayores beneficios de las expresiones lambda es la cantidad reducida de código. Como sabemos, las expresiones lambda solo se pueden usar con interfaces funcionales. Por ejemplo, Runnable es una interfaz, por lo que podemos aplicar fácilmente expresiones lambda.

  • La ejecución secuencial y paralela se admite al pasar comportamientos como parámetros en los métodos : al usar Stream API en Java 8, las funciones se pasan a los métodos de recopilación. Ahora bien, la responsabilidad de la colección es procesar los elementos en forma secuencial o paralela.

  • Mayor eficiencia : al usar Stream API y expresiones lambda, puede lograr una mayor eficiencia (ejecución paralela) en el caso de operaciones por lotes en colecciones. Además, las expresiones lambda ayudan a lograr una iteración interna de la colección, no una iteración externa.

defecto

  • Eficiencia operativa : sin cómputo paralelo, muchas veces la velocidad de cómputo no es más rápida que el bucle for tradicional. (La computación paralela a veces requiere calentamiento para mostrar ventajas de eficiencia)
  • Difícil de depurar : las expresiones lambda son difíciles de romper y no son fáciles de depurar.
  • No es fácil de entender : si otros programadores no han aprendido expresiones lambda, el código no es fácil de entender para programadores en otros lenguajes (la razón por la que aprendí expresiones lambda es que no puedo entender el código de expresión lambda escrito por mis colegas)

Supongo que te gusta

Origin blog.csdn.net/qq_45171957/article/details/124001453
Recomendado
Clasificación