java8函数式编程-lambda表达式简介

1.1、概述

Lambda是jdk8中一个语法糖,可以对某些匿名内部类的写法进行简化,是函数式编程思想的一个体现,这使得我们可以不用关注什么对象,而是更关注我们对数据进行了什么操作

1.2、核心原则

可推导可省略

1.3、基本格式

  (参数列表)->{代码}
  idea: alt+enter替换

例一

我们可以在创建线程并启动时使用匿名内部类的写法:

new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Lambda测试开始");
        }
    }).start();

使用Lambda修改之后

new Thread( ()->{System.out.println("Lambda测试结束");} ).start();

例二

现有方法定义如下 ,其中IntBinaryOperator是一个接口。先使用匿名内部类调用该方法

 public static int calculateNum(IntBinaryOperator operator){
        int a = 10;
        int b = 20;
        return operator.applyAsInt(a, b);
    }

public static void main(String[] args) {
    
      int i = calculateNum(new IntBinaryOperator() {
        @Override
        public int applyAsInt(int left, int right) {
            return left+right; 
        }
    });
    
    System.out.println(i);
}

Lambda写法:

    public static void main(String[] args) {
        int i = calculateNum((int left, int right) -> {
            return left + right;
        });
        System.out.println(i);
    }

例三

现有方法定义如下,其中InterPredicate是一个接口,先试用匿名内部类调用该方法

public static void PrintNum(IntPredicate pred) {
      int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
      for (int i : arr) {
          if (pred.test(i)) {
              System.out.println(i);
          }
      }
  }


public static void main(String[] args) {
    PrintNum(new IntPredicate() {
        @Override
        public boolean test(int value) {
            return value % 2 == 0;
        }
    });
}

Lambda写法:

 public static void main(String[] args) {
        PrintNum(value -> {value % 2 == 0} );
    }

1.4、省略规则

  • 参数类型可以省略
  • 参数只有一个时,( ) 可以省略
  • 方法体只有一句代码时,{ } 可以省略
  • 方法体重唯一语句是return时,省略大括号的同时return也要省略

1.5、方法引用

有时候多个lambda表达式实现函数是一样的话,可以封装成通用方法,以便于维护,这时候可以用方法引用实现

语法:对象 : : 方法

假如是static方法,可以直接 类名 : : 方法

实例如下:

// 对象::方法
public class test {

    public static void main(String[] args) {

        test class_test = new test();
        If if1 = class_test::method;
        System.out.println(if1.test(1));

    }

    public int method(int a) {
        return a - 2;
    }

    interface If {
        int test(int a);
    }

}
// 类名::方法
public class test {

    public static void main(String[] args) {
        If if1 = test::method;
        System.out.println(if1.test(1));
    }

    public static int method(int a) {
        return a - 2;
    }

    interface If {
        int test(int a);
    }
}

1.6、构造方法引用

如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用

语法:类名::new

实例:

首先定义一个Person( name, age )实体类,实现有参和无参构造方法和toString

// 实体类部分代码
  private String name;
  private int age;
  
  public Person() {
      System.out.println("无参构造方法");
  }
  
  public Person(String name, int age) {
      System.out.println("有参构造方法");
      this.name = name;
      this.age = age;
  }
 
   public class test {
    // 1、一般写法
    public static void main(String[] args) {
        PersonService1 personService1 = new PersonService1() {
            @Override
            public Person getPerson() {
                return new Person();
            }
        };
        System.out.println(personService1.getPerson());
    }
    
    // 2、 lambda表达式
      public static void main(String[] args) {
        PersonService1 personService1 = () -> new Person();
        System.out.println(personService1.getPerson());
    }
    
    // 3、类名::new
    public static void main(String[] args) {
        PersonService1 personService1 = Person::new;
        System.out.println(personService1.getPerson());
        
        PersonService2 personService2 = Person::new;
        System.out.println(personService2.getPerson("Akiko",18));
    }
    

    interface PersonService1 {
        Person getPerson();
    }

    interface PersonService2 {
        Person getPerson(String name, int age);
    }

}

1.7、综合实例

    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person("aa", 1));
        list.add(new Person("bb", 4));
        list.add(new Person("cc", 3));
        list.add(new Person("dd", 2));

        list.sort((o1, o2) -> o1.getAge() - o2.getAge());
        list.forEach(System.out::println);

    }

1.8、@FunctionalInterface注解

这个注解是函数式接口注解,所谓的函数式接口,首先是一个接口,然后就是在这个接口中只能有一个抽象方法

也称为SAM接口,即Single Abstract Method interfaces

特点:

  • 接口有且仅有一个抽象方法
  • 允许定义静态方法
  • 允许定义默认方法
  • 允许java.lang.Object中的public方法
  • 该注解不是必须的,如果一个接口符合函数式接口定义,name加不加该注解都没有影响,加上该注解能更好的让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionalInterface,那么编译器会报错

实例:

  // 正确的函数式接口
  @FunctionalInterface
  public interface CorrectInterface{

      // 抽象方法
      public void sub();

      // java.lang.Object中的public方法
      public boolean equals(Object o);

      // 默认方法
      public default void  defaultMethod(){}

      // 静态方法
      public  static  void   staticMethod(){}
  }


  // 错误的函数式接口,有多个抽象方法
  // @FunctionalInterface
  public interface  ErrorInterface{
      void add();
      void sub();
  }

1.9、系统内置函数式接口

在jdk的java.util.funciton包下,有一系列内置函数式接口

posted @ 2022-09-07 13:31  Milo_Carey  阅读(92)  评论(2)    收藏  举报