数据结构|数据结构 Java数据结构 --- Lambda表达式


文章目录

  • Lambda表达式
  • 1. Lambda表达式的背景
    • 1.1 Lambda表达式的语法
    • 1.2 函数式接口
  • 2. Lambda表达式的基本使用
    • 2.1 无返回值无参数
    • 2.2 无返回值一个参数
    • 2.3 无返回值多个参数
    • 2.4 有返回值无参数
    • 2.5 有返回值一个参数
    • 2.6 有返回值多个参数
    • 2.7 PriorityQueue使用示例
    • 2.8 语法精简
  • 3. 变量捕获
    • 3.1 匿名内部类的变量捕获
    • 3.2 Lambda的变量捕获
  • 4. Lambda在集合当中的使用
    • 4.1 Collection接口
    • 4.2 List接口
    • 4.3 Map接口
  • 5. 总结
  • 优点:
  • 缺点:

Lambda表达式 1. Lambda表达式的背景 Lambda表达式是JDK 1.8中一个重要的新特性。
lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。
Lambda 表达式(Lambda expression)可以看作是一个匿名函数,基于数学中的λ演算得名,也可称为闭包(Closure) 。
1.1 Lambda表达式的语法 基本语法:(parameters)->expression 或 (parameters)->{statements; }
Lambda表达式由三部分组成:
  1. paramaters: 类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。
  2. ->: 可理解为“被用于”的意思
  3. 方法体: 可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。
// 1. 不需要参数,返回值为 2 () -> 2; // 2. 接收一个参数(数字类型),返回其2倍的值 x -> 2 * x; // 3. 接受2个参数(数字),并返回他们的和 (x, y) -> x + y; // 4. 接收2个int型整数,返回他们的乘积 (int x, int y) -> x * y; // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) (String s)->System.out.print(s);

1.2 函数式接口 函数式接口定义: 一个接口有且只有一个抽象方法 。
【数据结构|数据结构 Java数据结构 --- Lambda表达式】注意:
  1. 如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口
  2. 如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的。
定义方式:
@FunctionalInterface interface NoParameterNoReturn { void test(); // 只能有一个抽象方法 }

另一种方式:
@FunctionalInterface interface NoParameterNoReturn { void test(); // 只能有一个抽象方法 default void test2(){ System.out.println("111"); } }

数据结构|数据结构 Java数据结构 --- Lambda表达式
文章图片

2. Lambda表达式的基本使用 2.1 无返回值无参数
//无返回值无参数 @FunctionalInterface interface NoParameterNoReturn { void test(); } public class Test { public static void main2(String[] args) { //无返回值无参数 NoParameterNoReturn parameterNoReturn = ()-> System.out.println("重写方法"); } }

2.2 无返回值一个参数
// 无返回值一个参数 @FunctionalInterface interface OneParameterNoReturn { void test(int a); } public class Test { public static void main(String[] args) { //无返回值有一个参数 OneParameterNoReturn oneParameterNoReturn = (a)->{System.out.println(a); }; oneParameterNoReturn.test(10); OneParameterNoReturn oneParameterNoReturn1 = a-> System.out.println(a); oneParameterNoReturn1.test(10); OneParameterNoReturn oneParameterNoReturn2 = System.out::println; oneParameterNoReturn2.test(10); } }

2.3 无返回值多个参数
//无返回值多个参数 @FunctionalInterface interface MoreParameterNoReturn { void test(int a,int b); } public class Test { public static void main(String[] args) { MoreParameterNoReturn moreParameterNoReturn = (a,b)->{ System.out.println(a+b); }; moreParameterNoReturn.test(10,20); MoreParameterNoReturn moreParameterNoReturn1 = (a, b) -> System.out.println(a+b); moreParameterNoReturn1.test(20,30); } }

2.4 有返回值无参数
//有返回值无参数 @FunctionalInterface interface NoParameterReturn { int test(); } public class Test { public static void main(String[] args) { NoParameterReturn noParameterReturn = ()->{return 10; }; int ret = noParameterReturn.test(); System.out.println(ret); NoParameterReturn noParameterReturn1 = ()->10; int ret1 = noParameterReturn1.test(); System.out.println(ret1); } }

2.5 有返回值一个参数
//有返回值一个参数 @FunctionalInterface interface OneParameterReturn { int test(int a); } public class Test { public static void main(String[] args) { OneParameterReturn oneParameterReturn = (a) -> {return a+11; }; int ret = oneParameterReturn.test(10); System.out.println(ret); OneParameterReturn oneParameterReturn1 = a -> a+11; System.out.println(oneParameterReturn1.test(10)); } }

2.6 有返回值多个参数
//有返回值多参数 @FunctionalInterface interface MoreParameterReturn { int test(int a,int b); } public class Test { public static void main(String[] args) { MoreParameterReturn moreParameterReturn = (a,b) -> {return a+b; }; moreParameterReturn.test(10,20); MoreParameterReturn moreParameterReturn1 = (a,b) -> a+b; System.out.println(moreParameterReturn1.test(30,40)); } }

2.7 PriorityQueue使用示例 数据结构|数据结构 Java数据结构 --- Lambda表达式
文章图片

2.8 语法精简
  1. 参数类型可以省略,如果需要省略,每个参数的类型都要省略。
  2. 参数的小括号里面只有一个参数,那么小括号可以省略
  3. 如果方法体当中只有一句代码,那么大括号可以省略
  4. 如果方法体中只有一条语句,其是return语句,那么大括号可以省略,且去掉return关键字。
3. 变量捕获 Lambda 表达式中存在变量捕获 ,了解了变量捕获之后,我们才能更好的理解Lambda 表达式的作用域 。Java当中的匿名类中,会存在变量捕获。
3.1 匿名内部类的变量捕获
class Test1{ public void func(){ System.out.println("func"); } } public class TestDemo { public static void main(String[] args) { int a = 100; new Test1(){ @Override public void func() { System.out.println("内部类,重写了func方法"); System.out.println("捕获变量, 要么是常量,要么未发生的变量" + a); } }.func(); } }

数据结构|数据结构 Java数据结构 --- Lambda表达式
文章图片

在上述代码当中的变量a就是,捕获的变量。这个变量要么是被final修饰,如果不是被final修饰的 你要保证在使用之前,没有修改。
错误示例1:
数据结构|数据结构 Java数据结构 --- Lambda表达式
文章图片

错误示例2:
数据结构|数据结构 Java数据结构 --- Lambda表达式
文章图片

3.2 Lambda的变量捕获
@FunctionalInterface interface NoParameterNoReturn { void test(); } public static void main(String[] args) { int a = 10; NoParameterNoReturn noParameterNoReturn = ()->{ // a = 99; error System.out.println("捕获变量:"+a); }; noParameterNoReturn.test(); }

4. Lambda在集合当中的使用 为了能够让Lambda和Java的集合类集更好的一起使用,集合当中,也新增了部分接口,以便与Lambda表达式对接。
对应的接口 新增的方法
Collection removeIf() spliterator() stream() parallelStream() forEach()
List replaceAll() sort()
Map getOrDefault() forEach() replaceAll() putIfAbsent() remove() replace() computeIfAbsent() computeIfPresent() compute() merge()
4.1 Collection接口 forEach()方法演示
使用示例:
class Test1{ public void func(){ System.out.println("func"); } } public class TestDemo { public static void main(String[] args) { ArrayList> list = new ArrayList<>(); list.add("ze"); list.add("www"); list.add("qwer"); list.add("lambda"); list.forEach(new Consumer>() { @Override public void accept(String s) { System.out.println(s); } }); list.forEach(s-> System.out.println(s)); } }

数据结构|数据结构 Java数据结构 --- Lambda表达式
文章图片

4.2 List接口 sort()方法的演示
使用示例:
public static void main(String[] args) { ArrayList> list = new ArrayList<>(); list.add("ze"); list.add("www"); list.add("qwer"); list.add("lambda"); list.sort(new Comparator>() { @Override public int compare(String o1, String o2) { return o1.length()-o2.length(); } }); System.out.println(list); list.sort((o1, o2) -> o1.length()-o2.length()); System.out.println(list); }

数据结构|数据结构 Java数据结构 --- Lambda表达式
文章图片

4.3 Map接口 forEach()方法
代码示例:
public static void main(String[] args) { HashMap map = new HashMap<>(); map.put(1,"ze"); map.put(2,"www"); map.put(3,"qwer"); map.put(4,"lambda"); map.forEach(new BiConsumer() { @Override public void accept(Integer integer, String s) { System.out.println("key:"+integer+"value:"+s); } }); map.forEach((key,value)-> System.out.println("key:"+key+"value:"+value)); }

数据结构|数据结构 Java数据结构 --- Lambda表达式
文章图片

5. 总结 Lambda表达式的优点很明显,在代码层次上来说,使代码变得非常的简洁。缺点也很明显,代码不易读。
优点:
  1. 代码简洁,开发迅速
  2. 方便函数式编程
  3. 非常容易进行并行计算
  4. Java 引入 Lambda,改善了集合操作
缺点:
  1. 代码可读性变差
  2. 在非并行计算中,很多计算未必有传统的 for 性能要高
  3. 不容易进行调试

    推荐阅读