Java Lambda 表达式

Java Lambda表达式

Lambda 表达式被使用作提供一个功能接口的具体实现。节约代码。

在表达式中,不需要再定义方法提供实现,只需要编写具体实现的方法。

Lambda表达式会被视为一个函数,因此编译器不会创建.class文件

方法接口

在Lambda表达式中,提供了方法接口的实现方式。如果一个接口只有一个抽象方法就可以称作是方法接口。

Java中提供了一个注解 @FunctionalInterface,可以用它声明方法接口。

语法

(argument-list) -> {body}

一个表达式主要包含三部分:

  • Argument-list :变量清单(可以为空)
  • Arrow-token:箭头
  • body:包含lambda表达式和语句

常用方式

(p1) -> {  
//只有一个参数,不需要指定类型,可以不用括号
}  
() -> {  
 System.out.println("Hello World");
}  
(p1,p2) -> {  return p1 + p2; }
(p1,p2) -> p1+p2; 
//上面两种情况相同,只有一句返回值时,不需要return和大括号
//如果表达式正文只有一条语句,则必须包含在大括号中,返回类型也要和匿名返回类型相同
() -> { return 3.1415 };

方法引用

双冒号::操作符是Java中的方法引用。当使用方法引用时,目标引用方法::之前,目标引用提供的方法名放在::之后,即目标引用::方法

Person::getAge;

Function 对象进行操作

// 获取 getAge 方法的 Function 对象
Function<Person, Integer> getAge = Person::getAge;
// 传参数调用 getAge 方法
Integer age = getAge.apply(p);

目标引用的参数类型是 Function<T,R>T 表示传入类型,R 表示返回类型。

比如,表达式 person -> person.getAge();,传入参数是 person,返回值是 person.getAge(),那么方法引用 Person::getAge 就对应着 Function<Person,Integer> 类型。

使用示例

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester tester = new Java8Tester();
        
      // 类型声明,参数类型的声明需要保持一致,即全部同时声明或不声明
      MathOperation addition = (int a, int b) -> a + b;
        
      // 不用类型声明
      MathOperation subtraction = (a, b) -> a - b;
        
      // 大括号中的返回语句
      MathOperation multiplication = (int a, int b) -> { return a * b; };
        
      // 没有大括号及返回语句。只有一句的时候,可以不包含return关键字
      MathOperation division = (int a, int b) -> a / b;
        
      System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
      System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
      System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
      System.out.println("10 / 5 = " + tester.operate(10, 5, division));
        
      // 不用括号
      GreetingService greetService1 = message ->
      System.out.println("Hello " + message);
        
      // 用括号
      GreetingService greetService2 = (message) ->
      System.out.println("Hello " + message);
        
      greetService1.sayMessage("Runoob");
      greetService2.sayMessage("Google");
       
       //循环
       List<String> list1 = Arrays.asList("hello","good");
       list1.forEach(
                (n) -> System.out.println(n)
       );
   }
   interface MathOperation {
      int operation(int a, int b);
   }
   interface GreetingService {
      void sayMessage(String message);
   }
   private int operate(int a, int b, MathOperation mathOperation){
      return mathOperation.operation(a, b);
   }
}

注意

变量作用域

  1. 如果一个参数声明了类型,则所有的参数都需要声明变量类型
  2. 在Lambda表达式的变量中,不能和函数中声明的临时变量重复

Lambda表达式和匿名类的区别

两者的主要区别在于关键词的使用。对于匿名类,关键词this解释为匿名类,但是对Lambda表达式,关键词this会被写作时Lambda的外部类。

而造成这样的区别的主要原因就是两者的编译方法不同。Java编译器会编译Lambda表达式并将其转化为类中的私有函数,使用 Java 7 中新加的 invokedynamic 指令动态绑定该方法。参考

常用场景

1.创建线程对象

public class ThreadTest{
    public static void main(){
        Runnable r1 = () -> {
            System.out.println("Thread1 is running ...");
        };
        Thread t1 = new Thread(r1);
        t1.start();
        Runnable r2 = () -> {
            System.out.println("Thread2 is running ...");
        };
        Thread t2 = new Thread(r2);
        t2.start();
    }
}

2.集合框架的使用

Lambda表达式可以在集合框架中使用。可以提供高效简洁的方式实现迭代、过滤、获取数据。

使用场景

  • 比较器 Comparator
  • 过滤器 Filter
  • 事件监听器 Event Listener
public class collectionFrameWorkLambda {
    public static void main(String[] args) {
        List<Product> list = new ArrayList<>();
        //Adding Products
        list.add(new Product(1,"HP Laptop",25000f));
        list.add(new Product(3,"Keyboard",300f));
        list.add(new Product(2,"Dell Mouse",150f));
        //implementing lambda expression
        //Comparator 比较器
        Collections.sort(list,
                (p1,p2)->(p1.name.compareTo(p2.name))
        );
        for (Product product : list) {
            System.out.println(product.id+" "+ product.name+" "+ product.price);
        }
        //Filter Collection Data 过滤器
        Stream<Product> productStream = list.stream().filter(product -> (product.price > 20000f));
        productStream.forEach(
                product -> System.out.println(product.name+":"+product.price)
        );
        //Event Listener 事件监听
        JTextField tf = new JTextField();
        tf.setBounds(50, 50, 150, 20);
        JButton button = new JButton("click");
        button.setBounds(80, 100, 70, 30);

        // lambda expression implementing here.
        button.addActionListener(e -> tf.setText("hello swing"));

        JFrame f = new JFrame();
        f.add(tf);
        f.add(button);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(null);
        f.setSize(300, 200);
        f.setVisible(true);
    }
}
class Product {
    int id;
    String name;
    float price;
    public Product(int id, String name, float price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }
}

参考:

原文地址:https://www.cnblogs.com/ginko/p/15173523.html