Lamda表达式


文章目录

  • Lamda表达式
  • 前言
  • 一、Lambda基本概念
  • 1.背景
  • 2.Lambda表达式语法
  • 3.Lambda表达式五种不同的形式
  • 4.引用值,而不是变量
  • 二、Lambda表达式使用方式
  • 1.无参数无返回值
  • 2.无参数有返回值
  • 3.有参数无返回值
  • 4.有参数有返回值
  • 三、Lambda表达式变量作用域
  • 四、集合中Lambda表达式的应用



前言

一、Lambda基本概念

1.背景

Java8的最大变化是引入了Lambda表达式,它是所有Java8特性内容的基础——一种紧凑的,传递行为的方式。lambda表达式允许你通过表达式来代替功能接口,lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体, Lambda 表达式(Lambda expression)可以看作是一个匿名函数,也称为闭包

2.Lambda表达式语法

基本语法: (parameters) -> expression 或 (parameters) ->{ statements; }
Lambda表达式由三部分组成:
parameters:参数,类似方法中的形参列表,这里的参数是函数式接口里的参数
->:可理解为“被用于”的意思
方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不返回

3.Lambda表达式五种不同的形式

//1、无需要参数,使用空括号()表示没有参数。
//该Lambda表达式实现了Runnable接口,该接口也只有一个run方法,没有参数,返回值类型为void
Runnable noArguments = () -> System.out.println("Hello World")
// 2. 接收一个参数,可以省略括号,返回其2倍的值
x -> 2 * x
//3. Lambda表达式主体不仅可以是表达式,也可以是一段代码块,使用大括号{}将代码括起来。
() ->{
 	System.out.println("Hello");
 	System.out.println("World")
}
//4.Lambda表达式可以包含多个参数的方法。接受2个参数(数字),并返回他们的和
(x,y)->x+y;
//5.声明是参数类型,也可以是多个参数。接收2个int型整数,返回他们的和
(int x,int y)->x+y;

4.引用值,而不是变量

Java8虽然放松了对非final变量的引用,但是该变量在既成事实上必须是final。虽然无需将变量声明为final,但是在lamdba表达式中,也无法用作非终态变量。不然编译器就会报错
既成事实上得final是指只能给该变量赋值一次,换句话说,lambda表达式引用得是值,而不是变量,如下:
1、name就是一个既成事实的final变量

private static void streamTest( List<PersonVO> list,PersonVO personVO) {
        String name=personVO.getName();
        list.stream().filter(e-> name.equals(e.getName())).collect(Collectors.toList());
 }

2、下面试图给name重新赋值,然后在lanbda去引用它,编译器就会报错,提示该变量必须是一个final。

java list 拉姆达取交集 jdk8拉姆达表达式_开发语言


需要修改如下,重新定义一个finalName给lanbda使用

private static void streamTest( List<PersonVO> list,PersonVO personVO) {
        String name=personVO.getName();
        name="asda";
        String finalName = name;
        list.stream().filter(e-> finalName.equals(e.getName())).collect(Collectors.toList());
    }

这种行为也解释了为什么Lambda表达式也被称为闭包,未赋值的变量与周围环境隔离起来,进而被绑定到一个特定的值

二、Lambda表达式使用方式

Lambda 表达式只能实现函数式接口,什么是函数式接口呢?就是一个接口有且只有一个抽象方法

1.无参数无返回值

() -> { System.out.println("无参数无返回值");}

2.无参数有返回值

() -> { return "无参数有返回值"}

3.有参数无返回值

1、一个参数
param ->{System.out.println("无参数无返回值")}
2、多个参数
(param1,param2)->{System.out.println("无参数无返回值")}

4.有参数有返回值

1、一个参数
param ->{return param}
2、多个参数
(param1,param2)-{return param1+param2}

代码示例如下:

public class DomeLambda {
    interface NoParameterNoReturn {
        // 无参数无返回值
        void test();
    }
    interface OneParameterNoReturn {
        // 一个参数无返回值
        void test(String param);
    }
    interface TwoParameterNoReturn {
        // 两个参数无返回值
        void test(String param1, String param2);
    }
    interface NoParameterHasReturn {
        // 无参数有返回值
        String test();
    }
    interface OneParameterHasReturn {
        // 无参数有返回值
        String test(String param);
    }
    interface TwoParameterHasReturn {
        // 无参数有返回值
        String test(String param1,String param2);
    }
    public static void main(String[] args) {
        //1、无参数无返回值
        NoParameterNoReturn noParameterNoReturn = () -> {
            System.out.println("无参数无返回值");
        };
        noParameterNoReturn.test();
        //2、一个参数无返回值
        OneParameterNoReturn oneParameterNoReturn= param ->{
            System.out.println(param);
        };
        oneParameterNoReturn.test("一个参数无返回值");
        //两个参数,无返回值
        TwoParameterNoReturn twoParameterNoReturn = (param1,param2)->{
            System.out.println(param1+param2);
        };
        twoParameterNoReturn.test("两个参数","无返回值");
        //3、无参数有返回值
        NoParameterHasReturn noParameterHasReturn =()->{
            return  "无参数有返回值";
        };
        System.out.println(noParameterHasReturn.test());
        //4、有参数有返回值
        OneParameterHasReturn parameterHasReturn =param ->{
            return param;
        };
        System.out.println(parameterHasReturn.test("有参数有返回值"));

        TwoParameterHasReturn twoParameterHasReturn=(param1, param2) ->{
          return param1+param2;
        };
        System.out.println(twoParameterHasReturn.test("两个参数","有返回值"));
    }
}

三、Lambda表达式变量作用域

前面说的Lambda表达式是引用值,而不是变量。Lambda 表达式中使用的局部变量可以不用声明为 final,但是必须不可被后面的代码修改,即隐性的具有 final 的语义。

public class DomeLambda {
	 interface TestScope {
        void test();
    }
    public static void main(String[] args) {
     // 定义一个局部变量,但是后面不能对该变量进行修改,不然就会编译报错,即前面隐形的定义final
    String name ="test" ;
    TestScope testScope =()->{
            System.out.println("局部变量 age = " + name );
        };
        testScope.test();
}

四、集合中Lambda表达式的应用

在 Java 1.8 中给集合新增了很多方法,方法的参数类型是函数式接口,所以在使用这些方法时,可以大量使用 Lambda 表达式,让我们的代码更简洁紧凑。

接口

新增方法

Iterable

default void forEach(Consumer<? super T> action)

Collection

default boolean removeIf(Predicate<? super E> filter)

List

default void sort(Comparator<? super E> c)

default void replaceAll(UnaryOperator operator)

Map

comparingByKey(Comparator<? super K> cmp)

comparingByValue(Comparator<? super V> cmp)

default void forEach(BiConsumer<? super K, ? super V> action)

default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function)

default V merge(K key, V value,BiFunction<? super V, ? super V, ? extends V> remappingFunction)