当前位置:   article > 正文

JDK8的新特性--Lambda表达式_;&$clalho8&菧@mhvo)

;&$clalho8&菧@mhvo)

lambda表达式

概念: 语法:

注意: 函数式接口:接口中只有一个抽象方法。

(参数1,参数2): 抽象方法的参数

->: 分隔符

{}:表示抽象方法的实

例子:

  1. package com.demo01;
  2. /**
  3. * @Author Li Qinghua
  4. * @Create 2022/7/19 14:38
  5. */
  6. public class TestLambda {
  7. public static void main(String[] args) {
  8. //匿名内部类
  9. Runnable r1=new Runnable() {
  10. @Override
  11. public void run() {
  12. System.out.println("Runnable");
  13. }
  14. };
  15. Thread t1=new Thread(r1);
  16. t1.start();
  17. Runnable r2=()->{
  18. System.out.println("这是Lambda表达式的Runnable");
  19. };
  20. Thread t2=new Thread(r2);
  21. t2.start();
  22. Thread t3=new Thread(()->{
  23. System.out.println("这是Lambda表达式的匿名内部Runnable");
  24. });
  25. t3.start();
  26. }
  27. }

分析代码:

  • Thread 类需要 Runnable 接口作为参数,其中的抽象 run 方法是用来指定线程任务内容的核心

  • 为了指定 run 的方法体,不得不需要 Runnable 接口的实现类

  • 为了省去定义一个 Runnable 实现类的麻烦,不得不使用匿名内部类

  • 必须覆盖重写抽象 run 方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错

  • 而实际上,似乎只有方法体才是关键所在。

这时可以使用lambda表示完成上面的要求。

前提:必须是函数式接口。

简化匿名内部类的使用,语法更加简单。

1 .无参无返回值

  1. package com.demo03;
  2. /**
  3. * @Author Li Qinghua
  4. * @Create 2022/7/19 15:34
  5. */
  6. public class TestSwim {
  7. public static void main(String[] args) {
  8. method(()-> System.out.println("在游泳"));
  9. }
  10. public static void method(Swim s){
  11. s.swim();
  12. }
  13. }
  14. @FunctionalInterface
  15. interface Swim{
  16. public void swim();
  17. }

2 有参数有返回值的Lambda

下面举例演示 java.util.Comparator 接口的使用场景代码,其中的抽象方法定义为:

  • public abstract int compare(T o1, T o2);

当需要对一个对象集合进行排序时, Collections.sort 方法需要一个 Comparator 接口实例来指定排序的规则。

  1. package com.demo02;
  2. import java.util.ArrayList;
  3. import java.util.Collections;
  4. import java.util.Comparator;
  5. import java.util.List;
  6. /**
  7. * @Author Li Qinghua
  8. * @Create 2022/7/19 15:08
  9. */
  10. public class TestStudentSort {
  11. public static void main(String[] args) {
  12. List<Student> list=new ArrayList<>();
  13. list.add(new Student("李MM",29,176));
  14. list.add(new Student("李PP",19,174));
  15. list.add(new Student("李AA",23,183));
  16. list.add(new Student("李RR",22,179));
  17. Comparator<Student> comparator=new Comparator<Student>() {
  18. @Override
  19. public int compare(Student o1, Student o2) {
  20. return o2.getAge()-o1.getAge();
  21. }
  22. };
  23. Collections.sort(list,comparator);
  24. for(Student s:list){
  25. System.out.println(s);
  26. }
  27. System.out.println("=================");
  28. Comparator<Student> comparator1=(Student s1,Student s2)->{
  29. return (int) (s2.getHigh()-s1.getHigh());
  30. };
  31. Collections.sort(list,comparator1);
  32. for(Student s:list){
  33. System.out.println(s);
  34. }
  35. System.out.println("============");
  36. Collections.sort(list,(o1,o2)-> o2.getAge()-o1.getAge());
  37. for(Student s:list){
  38. System.out.println(s);
  39. }
  40. }
  41. }
  42. class Student{
  43. private String name;
  44. private int age;
  45. private double high;
  46. @Override
  47. public String toString() {
  48. return "Student{" +
  49. "name='" + name + '\'' +
  50. ", age=" + age +
  51. ", high=" + high +
  52. '}';
  53. }
  54. public Student(String name, int age, double high) {
  55. this.name = name;
  56. this.age = age;
  57. this.high = high;
  58. }
  59. public String getName() {
  60. return name;
  61. }
  62. public void setName(String name) {
  63. this.name = name;
  64. }
  65. public int getAge() {
  66. return age;
  67. }
  68. public void setAge(int age) {
  69. this.age = age;
  70. }
  71. public double getHigh() {
  72. return high;
  73. }
  74. public void setHigh(double high) {
  75. this.high = high;
  76. }
  77. }

3.详细介绍lambda表达式

4. 函数式接口

 内置函数式接口的由来

  1. public class Test03 {
  2. public static void main(String[] args) {
  3. Operater o=arr -> {
  4. int sum=0;
  5. for(int n:arr){
  6. sum+=n;
  7. }
  8. System.out.println("数组的和为:"+sum);
  9. };
  10. fun(o);
  11. }
  12. public static void fun(Operater operater){
  13. int[] arr={2,3,4,5,6,7,11};
  14. operater.getSum(arr);
  15. }
  16. }
  17. @FunctionalInterface
  18. interface Operater{
  19. //求数组的和
  20. public abstract void getSum(int[] arr);
  21. }

分析

我们知道使用Lambda表达式的前提是需要有函数式接口。而Lambda使用时不关心接口名,抽象方法名,只关心抽 象方法的参数列表和返回值类型。因此为了让我们使用Lambda方便,JDK提供了大量常用的函数式接口。

常见得函数式接口

java.util.function保存

4.1 Consumer<T>

有参数,无返回值。

  1. package edu.demo04;
  2. import java.util.function.Consumer;
  3. /**
  4. * @Author Li Qinghua
  5. * @Create 2022/7/19 20:36
  6. */
  7. public class Test01 {
  8. public static void main(String[] args) {
  9. Consumer<Integer[]> c=nums->{
  10. int sum=0;
  11. for(int n:nums){
  12. sum+=n;
  13. }
  14. System.out.println(sum);
  15. };
  16. method(c);
  17. }
  18. //调用某个方法时,该方法需要的参数为接口类型,这时就应该能想到使用lambda
  19. public static void method(Consumer<Integer[]> consumer){
  20. Integer[] arr={1,2,3,4,5};
  21. consumer.accept(arr);
  22. }
  23. }

4.2 Supplier<T>供给型函数式接口

T:表示返回结果的泛型

无参,想有返回结果的函数式接口时使用Supplier

T get();

  1. package edu.demo04;
  2. import java.util.function.Supplier;
  3. /**
  4. * @Author Li Qinghua
  5. * @Create 2022/7/19 20:59
  6. */
  7. public class Test02 {
  8. public static void main(String[] args) {
  9. method(()->{
  10. return "Hello World";
  11. });
  12. }
  13. public static void method(Supplier<String> supplier){
  14. String str = supplier.get();
  15. System.out.println(str);
  16. }
  17. }

4.3 Function<T,R> 函数型函数式接口

T: 参数类型的泛型

R: 函数返回结果的泛型

有参,有返回 值时。

例子: 传入一个学生的姓名,求出该学生的年龄或者姓名。

  1. package edu.demo04;
  2. import java.util.function.Function;
  3. /**
  4. * @Author Li Qinghua
  5. * @Create 2022/7/19 21:04
  6. */
  7. public class Test03 {
  8. public static void main(String[] args) {
  9. Function<Student,Integer> function=(stu)->{
  10. return stu.getAge();
  11. };
  12. method(function);
  13. }
  14. public static void method(Function<Student,Integer> function){
  15. Integer age = function.apply(new Student("李QQ", 23));
  16. System.out.println(age);
  17. }
  18. }
  19. class Student{
  20. private String name;
  21. private int age;
  22. public Student(String name, int age) {
  23. this.name = name;
  24. this.age = age;
  25. }
  26. public String getName() {
  27. return name;
  28. }
  29. public void setName(String name) {
  30. this.name = name;
  31. }
  32. public int getAge() {
  33. return age;
  34. }
  35. public void setAge(int age) {
  36. this.age = age;
  37. }
  38. @Override
  39. public String toString() {
  40. return "Student{" +
  41. "name='" + name + '\'' +
  42. ", age=" + age +
  43. '}';
  44. }
  45. }

4.4 Predicated<T>

T: 参数的泛型

boolean test(T t);

当传入一个参数时,需要对该参数进行判断时,则需要这种函数。

  1. package com.demo07;
  2. import java.util.function.Predicate;
  3. /**
  4. * @Author Li Qinghua
  5. * @Create 2022/7/19 16:50
  6. */
  7. public class TestPredicated {
  8. public static void main(String[] args) {
  9. method(name->name.length()>3?true:false,"雷霆嘎巴");
  10. }
  11. public static void method(Predicate<String> predicate,String name){
  12. boolean b = predicate.test(name);
  13. System.out.println(b);
  14. }
  15. }

5. 方法引用

5.1 lambda表达式的冗余

  1. package com.demo08;
  2. import java.util.function.Consumer;
  3. /**
  4. * @Author Li Qinghua
  5. * @Create 2022/7/19 19:04
  6. * lambda 冗余 静态方法引用
  7. */
  8. public class Test01 {
  9. public static void main(String[] args) {
  10. Consumer<Integer> c1=(num)->{
  11. int sum=0;
  12. for (int i = 0; i <= num; i++) {
  13. sum+=i;
  14. }
  15. System.out.println(sum);
  16. };
  17. method(c1,100);
  18. getSum(100);
  19. }
  20. public static void method(Consumer<Integer> consumer,Integer num){
  21. consumer.accept(num);
  22. }
  23. public static void getSum(Integer num){
  24. int sum=0;
  25. for (int i = 0; i <=num; i++) {
  26. sum+=i;
  27. }
  28. System.out.println("和为:"+sum);
  29. }
  30. }

分析:

如果我们在Lambda中所指定的功能,已经有其他方法存在相同方案,那是否还有必要再写重复逻辑?可以直接“引 用”过去就好了:---方法引用。

静态方法引用

  1. package com.demo08;
  2. import java.util.function.Consumer;
  3. /**
  4. * @Author Li Qinghua
  5. * @Create 2022/7/19 19:04
  6. * lambda 冗余 静态方法引用
  7. */
  8. public class Test01 {
  9. public static void main(String[] args) {
  10. /*Consumer<Integer> c1=(num)->{
  11. int sum=0;
  12. for (int i = 0; i <= num; i++) {
  13. sum+=i;
  14. }
  15. System.out.println(sum);
  16. };*/
  17. Consumer<Integer> c2=Test01::getSum;
  18. //method(c1,100);
  19. method(c2,100);
  20. //getSum(100);
  21. }
  22. public static void method(Consumer<Integer> consumer,Integer num){
  23. consumer.accept(num);
  24. }
  25. public static void getSum(Integer num){
  26. int sum=0;
  27. for (int i = 0; i <=num; i++) {
  28. sum+=i;
  29. }
  30. System.out.println("和为:"+sum);
  31. }
  32. }

请注意其中的双冒号 :: 写法,这被称为“方法引用”,是一种新的语法。

5.2 什么是方法引用

 方法引用的分类

5.3 实例方法引用

实例方法引用,顾名思义就是调用已经存在的实例的方法,与静态方法引用不同的是类要先实例化,静态方法引用类无需实例化,直接用类名去调用。

  1. package com.demo08;
  2. import java.util.function.Supplier;
  3. /**
  4. * @Author Li Qinghua
  5. * @Create 2022/7/19 19:30
  6. */
  7. public class Test03 {
  8. public static void main(String[] args) {
  9. /*Person[] people={new Person("李AA",19),new Person("李UU",23),new Person("李NN",21)
  10. new Person("李OO",16)};*/
  11. Person p=new Person("李AA",23);
  12. Supplier<String> supplier=p::getName;
  13. method(supplier);
  14. }
  15. public static void method(Supplier<String> supplier){
  16. String s = supplier.get();
  17. System.out.println(s);
  18. }
  19. }
  20. class Person{
  21. private String name;
  22. private int age;
  23. public static int compareTo(Person p1,Person p2){
  24. return p2.getAge()-p1.getAge();
  25. }
  26. @Override
  27. public String toString() {
  28. return "Person{" +
  29. "name='" + name + '\'' +
  30. ", age=" + age +
  31. '}';
  32. }
  33. public String getName() {
  34. return name;
  35. }
  36. public void setName(String name) {
  37. this.name = name;
  38. }
  39. public int getAge() {
  40. return age;
  41. }
  42. public void setAge(int age) {
  43. this.age = age;
  44. }
  45. public Person(String name, int age) {
  46. this.name = name;
  47. this.age = age;
  48. }
  49. }

5.4对象方法引用

类名::实例方法. (参数1,参数2)->参数1.实例方法(参数2)

  1. package edu.demo05;
  2. import java.util.function.BiFunction;
  3. import java.util.function.Consumer;
  4. import java.util.function.Function;
  5. import java.util.function.Supplier;
  6. /**
  7. * @Author Li Qinghua
  8. * @Create 2022/7/20 14:40
  9. */
  10. public class Test03 {
  11. public static void main(String[] args) {
  12. Function<String,Integer> function=String::length;
  13. Integer len = function.apply("abc");
  14. System.out.println(len);
  15. System.out.println("~~~~~~~~~~~");
  16. //比较两个字符串的内容是否一致.T, U, R
  17. BiFunction<String,String,Boolean> bi=String::equals;
  18. Boolean b = bi.apply("abc", "efg");
  19. System.out.println(b);
  20. System.out.println("~~~~~~~~~~");
  21. Function<String,People> function1=People::new;
  22. People person = function1.apply("李四");
  23. System.out.println(person);
  24. }
  25. }
  26. class People{
  27. private String name;
  28. public People() {
  29. }
  30. public People(String name) {
  31. this.name = name;
  32. }
  33. public String getName() {
  34. return name;
  35. }
  36. public void setName(String name) {
  37. this.name = name;
  38. }
  39. @Override
  40. public String toString() {
  41. return "People{" +
  42. "name='" + name + '\'' +
  43. '}';
  44. }
  45. }

5.4构造方法引用

类名::new         (参数)->new 类名(参数)

  1. Function<String,People> function1=People::new;
  2. People person = function1.apply("李四");
  3. System.out.println(person);

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/726792
推荐阅读
相关标签
  

闽ICP备14008679号