[Gramática básica de Java] Explicar las expresiones Lambda de Java en detalle

1. Introducción

  • Las expresiones lambda son una nueva característica importante en Java SE8
  • Las expresiones lambda le permiten reemplazar interfaces funcionales con expresiones
  • Las expresiones lambda, al igual que los métodos, proporcionan una lista de parámetros normales y un cuerpo que usa esos parámetros.
  • La expresión lambda se puede considerar como una función anónima, llamado así por el cálculo de λ en matemáticas, también se puede llamar un cierre
  • Las expresiones lambda permiten utilizar una función como parámetro de método

2. Sintaxis de expresiones lambda

Forma básica: la expresión lambda consta de tres partes: parámetro, -> símbolo, cuerpo del método

(参数列表)->{
    
    方法体}

Reponer:

  • Las expresiones lambda pueden tener cero o más parámetros
  • El tipo del parámetro puede declararse explícitamente o no, y la JVM lo infiere implícitamente. Por ejemplo, (int a)y (a)tiene el mismo efecto
  • Cuando solo hay un parámetro y se puede deducir el tipo, se pueden omitir los paréntesis, por ejemplo, (a)el mismo aefecto que
  • Si el cuerpo del método de la expresión lambda tiene solo una instrucción, se pueden omitir las llaves
  • Si el cuerpo del método de la expresión lambda tiene solo una declaración y es el valor devuelto, puede omitir return

Ejemplo de código:

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

// 接收两个参数(数字类型),并返回它们的和
(x,y)->x+y
    
// 接收两个 int 类型参数,返回它们的乘积
(int x,int y)->x*y

// 接收一个 String 对象,并在控制台打印
(String s)->System.out.println(s)

3. Interfaz de función

SiUna interfaz tiene solo un método abstracto, y dicha interfaz se llama interfaz única. A partir de JDK8, Java usa expresiones Lambda yUna única interfaz se denomina interfaz funcional.

Darse cuenta:

  • Una interfaz es una interfaz funcional si solo tiene un método abstracto
  • Si declaramos una @FunctionInterfaceanotación , el compilador requerirá la interfaz de acuerdo a la definición de la interfaz funcional, por lo que esta interfaz solo puede tener un método abstracto, si se excede, el programa reportará un error al compilar

Código de muestra:

@functionInterface
interface A{
    
    
    void test();
}

4. El uso de expresiones lamdba

A continuación, demostraremos el uso de expresiones lambda

// 无返回值无参数 
@FunctionalInterface interface NoParameterNoReturn {
    
     void test(); }
// 无返回值一个参数 
@FunctionalInterface interface OneParameterNoReturn {
    
     void test(int a); }
// 无返回值多个参数 
@FunctionalInterface interface MoreParameterNoReturn {
    
     void test(int a,int b); }
// 有返回值无参数 
@FunctionalInterface interface NoParameterReturn {
    
     int test(); }
// 有返回值一个参数 
@FunctionalInterface interface OneParameterReturn {
    
     int test(int a); }
// 有返回值多参数 
@FunctionalInterface interface MoreParameterReturn {
    
     int test(int a,int b); }

public class TestDemo {
    
     
    public static void main(String[] args) {
    
     
        NoParameterNoReturn noParameterNoReturn = ()->{
    
     System.out.println("无参数无返回值"); };
        noParameterNoReturn.test(); 
        
        OneParameterNoReturn oneParameterNoReturn = (int a)->{
    
     System.out.println("无参数一个返回值:"+ a); };
        oneParameterNoReturn.test(10); 
        
        MoreParameterNoReturn moreParameterNoReturn = (int a,int b)->{
    
     System.out.println("无返回值多个参数:"+a+" "+b); };
        moreParameterNoReturn.test(20,30); 
        
        NoParameterReturn noParameterReturn = ()->{
    
     System.out.println("有返回值无参数!"); return 40; };
        //接收函数的返回值 
        int ret = noParameterReturn.test(); 
        System.out.println(ret); 
        
        OneParameterReturn oneParameterReturn = (int a)->{
    
     System.out.println("有返回值有参数!"); return a; };
        ret = oneParameterReturn.test(50); 
        System.out.println(ret); 
        
        MoreParameterReturn moreParameterReturn = (int a,int b)->{
    
     System.out.println("有返回值多个参数!"); return a+b; };
        ret = moreParameterReturn.test(60,70);
		System.out.println(ret); 
    } 
}

5. Captura de variables

5.1 Introducción

La captura de variables existe para clases locales y anónimas en Java

Solo después de comprender qué es la captura de variables, podemos comprender mejor el alcance de las expresiones lambda, porque las expresiones lambda también tienen captura de variables.

5.2 Captura de variables de clases internas anónimas

class A {
    
     
    public void func(){
    
     
        System.out.println("func()"); 
    } 
}
public class TestDemo {
    
     
    public static void main(String[] args) {
    
     
        int a = 100; 
        new Test(){
    
     
            @Override public void func() {
    
     
                System.out.println("我是内部类,且重写了func这个方法!");
                System.out.println("我是捕获到变量 a == "+a +" 我是一个常量,或者是一个没有改变过值的变量!"); 
            } 
        }; 
    } 
}

La variable a en el código anterior es una variable capturada. Esta variable es modificada por final o es necesaria para garantizar que la variable no se modifique cuando se usa en una clase interna anónima. Si se modifica, se producirá un error de compilación.

5.3 Captura de variables lambda

La captura de variables también es posible en Lambda

@FunctionalInterface interface A {
    
     
    void test(); 
}
public static void main(String[] args) {
    
     
    int a = 10; 
    NoParameterNoReturn noParameterNoReturn = ()->{
    
    
        // a = 99; 如果修改a,则会报错 
        System.out.println("捕获变量:"+a); 
    };
    noParameterNoReturn.test(); 
}

6. El uso de Lambda en las colecciones

Para que las clases de colección Lambda y Java funcionen mejor juntas, se han agregado algunas interfaces nuevas a la colección para acoplarse con expresiones Lambda.

interfaz correspondiente Método agregado
Recopilación removeIf()spliterator()stream()parallelStream()forEach()
Lista replaceAll()sort()
Mapa getDefault()forEach()replaceAll()putIfAbsent()remove()replace()computeIfAbsent()computeIfPresent()compute()merge()

Reponer:

Los forEach()métodos se java.lang.Interableheredan de la interfaz.

6.1 Interfaz de colección

Demostración usando el método forEach()

forEach()Código fuente: inserte la descripción de la imagen aquí

Ejemplo de código: uso de clases internas anónimas

public class TestDemo{
    
    
    public static void main(String[] args) {
    
    
        List<String> list=new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.forEach(new Consumer<String>() {
    
    
            @Override
            public void accept(String s) {
    
    
                System.out.print(s+" ");
            }
        });
    }
}
// 结果为:aaa bbb ccc

Ejemplo de código: uso de Lambda

public class TestDemo{
    
    
    public static void main(String[] args) {
    
    
        List<String> list=new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.forEach(s -> System.out.print(s+" "));
    }
}
// 结果为:aaa bbb ccc

6.2 Interfaz de lista

Demostración usando el método sort()

sort()Código fuente: inserte la descripción de la imagen aquí

Ejemplo de código: uso de clases internas anónimas

public class TestDemo{
    
    
    public static void main(String[] args) {
    
    
        List<String> list=new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.sort(new Comparator<String>() {
    
    
            @Override
            public int compare(String o1, String o2) {
    
    
                return o1.compareTo(o2);
            }
        });
        System.out.println(list);
    }
}
// 结果为:[aaa, bbb, ccc]

Ejemplo de código: uso de Lambda

public class TestDemo{
    
    
    public static void main(String[] args) {
    
    
        List<String> list=new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.sort((String o1,String o2)->o1.compareTo(o2));
        System.out.println(list);
    }
}
// 结果为:[aaa, bbb, ccc]

6.3 Interfaz del mapa

Demostrar usando el método forEach() de HashMap

HashMap 的 forEach()Código fuente:

inserte la descripción de la imagen aquí

Ejemplo de código: uso de clases internas anónimas

public class TestDemo{
    
    
    public static void main(String[] args) {
    
    
        Map<Integer,String> map=new HashMap<>();
        map.put(1,"aaa");
        map.put(2,"222");
        map.put(3,"333");
        map.forEach(new BiConsumer<Integer, String>() {
    
    
            @Override
            public void accept(Integer integer, String s) {
    
    
                System.out.println("Key="+integer+" Value="+s);
            }
        });
    }
}
/** 结果为:
Key=1 Value=aaa
Key=2 Value=222
Key=3 Value=333
*/

Ejemplo de código: uso de Lambda

public class TestDemo{
    
    
    public static void main(String[] args) {
    
    
        Map<Integer,String> map=new HashMap<>();
        map.put(1,"aaa");
        map.put(2,"222");
        map.put(3,"333");
        map.forEach((Integer integer,String s)->
                System.out.println("Key="+integer+" Value="+s));
    }
}
/** 结果为:
Key=1 Value=aaa
Key=2 Value=222
Key=3 Value=333
*/

7. Ventajas y desventajas de las expresiones Lambda

ventaja:

  • Código simple, desarrollo rápido
  • Cómoda programación funcional
  • Fácil de paralelizar
  • Java presenta Lambda para mejorar las operaciones de recolección

defecto:

  • Mala legibilidad del código
  • En la computación no paralela, es posible que muchos cálculos no tengan el alto rendimiento de los bucles for tradicionales.

Supongo que te gusta

Origin blog.csdn.net/weixin_51367845/article/details/122031877
Recomendado
Clasificación