Lambda表达式

文章详细介绍了Java中的Lambda表达式,它是对匿名类的一种简化,特别是当接口只有一个方法时。Lambda允许将功能作为方法参数,提供了简洁的语法。文章还提到了Lambda表达式的简写形式以及其在集合操作中的应用。此外,方法引用被介绍为一种替代Lambda的手段,当表达式仅调用已有方法时,方法引用提供了一种清晰的表示方式。文章列举了不同类型的引用,包括静态方法、实例方法和构造方法的引用。
摘要由CSDN通过智能技术生成

概述

  官网对lambda表达式的描述

  > 官网:https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

   One issue with anonymous classes is that if the implementation of your anonymous class is very simple, such as an interface that contains only one method, then the syntax of anonymous classes may seem unwieldy and unclear. In these cases, you're usually trying to pass functionality as an argument to another method, such as what action should be taken when someone clicks a button. Lambda expressions enable you to do this, to treat functionality as method argument, or code as data.

   匿名类的一个问题是,如果匿名类的实现非常简单,例如只包含一个方法的接口,那么匿名类的语法可能会显得笨拙和不清楚。在这些情况下,您通常会尝试将功能作为参数传递给另一个方法,例如当有人单击按钮时应该采取什么操作。 Lambda 表达式使您能够做到这一点,将功能视为方法参数,或将代码视为数据。

  > 描述中包含了三层含义

  - lambda表达式是对匿名类的简化

  - lambda使用的前提

  - 一个接口

  - 接口中包含一个方法

  - lambda表达式的理解:将功能作为参数传递给另一个方法

  示例代码

  - 创建并开启一个线程,使用匿名内部类的方式实现Runnable,重写run方法

publicstaticvoidmain(String[] args){newThread(newRunnable(){// 匿名内部类@Overridepublicvoidrun(){System.out.println("我是线程开启执行的代码");}}).start();}
  ```

  - Runnable接口中只有一个抽象方法run。用lambda表达式改写

// @FunctionalInterface// public interface Runnable {//    public abstract void run();// }publicstaticvoidmain(String[] args){newThread(()->System.out.println("我是线程开启执行的代码")).start();}
  ```

  语法

  基本语法

  > 从上述案例中,使用lambda表达式是对Runnable接口中的run方法进行了重写

  >

  > 格式:(抽象方法的参数列表) -> {重写的代码}

  示例代码

  > 删除集合中大于3的元素

  - 匿名内部类

List<Integer> list =newArrayList<>(Arrays.asList(1,2,3,4,5));
  list.removeIf(newPredicate<Integer>(){@Overridepublicbooleantest(Integer i){return i >3;}});System.out.println(list);// [1, 2, 3]
  ```

  - lambda表达式

List<Integer> list =newArrayList<>(Arrays.asList(1,2,3,4,5));
  list.removeIf((Integer i)->{return i >3;});System.out.println(list);// [1, 2, 3]
  ```

  - 说明

  简写语法

  > 参数的简写

> 参数的简写
>
> - 抽象方法参数的个数
>   - 空参:不省略。
>   - 一个参数:省略<span style="color:red;">小括号</span>,省略<span style="color:red;">参数类型</span>。
>     - 省略前:(Integer i) -> {}
>     - 省略后:i -> {}
>   - 多个参数:省略<span style="color:red;">参数类型</span>。
>     - 省略前:(String a, Integer b) -> {}
>     - 省略后: (a,b) -> {}
>
> 方法体的简写
>
> - 方法体中只有一行表达式:省略<span style="color:red;">大括号、return、分号</span>。
>   - 省略前:(Integer i) -> {return i > 3;}
>   - 省略后:i -> i > 3

  示例代码

  - lambda表达式

List<Integer> list =newArrayList<>(Arrays.asList(1,2,3,4,5));
  list.removeIf((Integer i)->{return i >3;});System.out.println(list);// [1, 2, 3]
  ```

  - 简写

List<Integer> list =newArrayList<>(Arrays.asList(1,2,3,4,5));
  list.removeIf(i -> i >3);System.out.println(list);// [1, 2, 3]
  ```

  原理

  debug调试

  - Demo.java

publicclassDemo{publicstaticvoidmain(String[] args){newThread(()->{System.out.println("我是线程启动后执行的代码");}).start();}}
  ```

  - debug运行

  - 说明

  - run:748,Thread(java.lang):调用Thread中的run方法

  - run:-1,1156060786(`org.example.Demo$$Lambda$1`):调用`Demo$$Lambda$1`中的run方法

  - `lambda$main$0:10`,Demo(org.example): 方法`lambda$main$0`中执行了 打印语句

  - 小结

  - `Demo$$Lambda$1`这个类中的run方法 调用 -----> `lambda$main$0`方法 -------> 执行 lambda表达式代码块的代码(打印语句)

  保留lambda语句产生的字节码文件

  - java命令+参数。在硬盘中产生一个新的class文件(Demo$$Lambda$1.class)

  java -Djdk.internal.lambda.dumpProxyClasses Demo.class
  ```

  

  - 将该文件拖入的idea中

  - `Demo$$Lambda$1`是Runnable的实现类

  - run方法中调用`Demo.lambda$main$0()`方法

  原理理解

  方法引用(Method references)

  概述

  官网对方法引用的描述

  > 官网:https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html

   You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, it's often clearer to refer to the existing method by name. Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.

   您可以使用 lambda 表达式来创建匿名方法。然而,有时 lambda 表达式除了调用现有方法之外什么都不做。在这些情况下,按名称引用现有方法通常会更清楚。方法引用使您能够做到这一点;它们是用于已具有名称的方法的紧凑、易于阅读的 lambda 表达式。

  > 描述中包含两层含义

  >

  > - 方法引用,用于labmda表达式中

  > - 前提:lambda 表达式除了调用现有方法之外什么都不做。(下一节语法中的案例进行说明)

  > - lambda表达式中的参数调用方法

  > - 示例:(String s) -> s.toLowerCase()

  > - labmda表达式中的参数作为其他方法的参数

  > - 示例:(Ineger i) -> String.valueOf(i)

  语法

  > 官网:https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html

  There are four kinds of method references:

  | Kind | Syntax | Examples |

  | ------------------------------------------------------------ | -------------------------------------- | ------------------------------------------------------------ |

  | Reference to a static method | `ContainingClass::staticMethodName` | `Person::compareByAge` `MethodReferencesExamples::appendStrings` |

  | Reference to an instance method of a particular object | `containingObject::instanceMethodName` | `myComparisonProvider::compareByName` `myApp::appendStrings2` |

  | Reference to an instance method of an arbitrary object of a particular type | `ContainingType::methodName` | `String::compareToIgnoreCase` `String::concat` |

  | Reference to a constructor | `ClassName::new` | `HashSet::new` |

  四种方法引用

  | 种类 | 语法 | 示例 |

  | ------------------------------------ | ------------------ | ------------------------------------------------------------ |

  | 引用静态方法 | `类名::静态方法名` | `Person::compareByAge` `MethodReferencesExamples::appendStrings` |

  | 对特定对象的实例方法的引用 | `对象名::方法名` | `myComparisonProvider::compareByName` `myApp::appendStrings2` |

  | 对特定类型的任意对象的实例方法的引用 | `类名::方法名` | `String::compareToIgnoreCase` `String::concat` |

  | 引用构造方法 | `类名::new` | `HashSet::new` |

  下面的案例中会用到Stream相关API,我们会在后续的文章中进行详细讨论。

  下面的案例中会用到Stream相关API,我们会在后续的文章中进行详细讨论。

  - 引用静态方法

// 将集合中的Integer 转换为 String, 并收集到一个新的集合中List<Integer> integerList =newArrayList<>(Arrays.asList(1,2,3,4,5));List<String> stringList = integerList.stream()// 参数i 作为String静态方法valueOf的参数。并且lambda表达式中除了方法的调用以外其他什么都没做// .map(i -> String.valueOf(i)).map(String::valueOf)// 引用String类中的静态方法valueOf。类名::静态方法名.collect(Collectors.toList());System.out.println(stringList);
  ```

  - 对特定对象的实例方法的引用

publicclassDemo{publicstaticvoidmain(String[] args){Test test =newTest();List<Integer> integerList =newArrayList<>(Arrays.asList(1,2,3,4,5));
          integerList.stream()/*
                      1.与静态方法不同,要想使用Test类中的show方法 需要先有Test类的实例
                      2.参数i 作为test对象show方法的参数
                      3.并且lambda表达式中除了方法的调用以外其他什么都没做
                   */// .forEach(i -> test.show(i));.forEach(test::show);// 引用test对象中的方法show。对象名::方法名}}classTest{publicvoidshow(Object o){System.out.println(o);}}
  ```

  - 对特定类型的任意对象的实例方法的引用

// 将集合中的元素转成大写,并收集到新的集合中List<String> list =newArrayList<>(Arrays.asList("a","b","c"));List<String> list2 = list.stream()/*
         1.参数s 作为toUpperCase方法的调用者
         2.并且lambda表达式中除了方法的调用以外其他什么都没做
         3.引用的类型为参数s的数据类型String
      */// .map(s -> s.toUpperCase()).map(String::toUpperCase)// 引用String类中的方法toUpperCase。类名::方法名.collect(Collectors.toList());
  ```

  - 引用构造方法

// 将集合中的元素转成Person对象,并收集到新的集合中publicclassDemo{publicstaticvoidmain(String[] args){List<String> stringList =newArrayList<>(Arrays.asList("张三","李四","王五"));List<Person> personList = stringList.stream()/*
                      1.参数s 作为Person类构造方法的参数
                      2.并且lambda表达式中除了方法的调用以外其他什么都没做
                   */// .map(s -> new Person(s)).map(Person::new)// 引用Person类中的构造方法。类名::new.collect(Collectors.toList());}}classPerson{privateString name;publicPerson(String name){this.name = name;}}
  ```
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值