zoukankan      html  css  js  c++  java
  • Java重温学习笔记,Java8新特性:Lambda 表达式

    Lambda 表达式,也称闭包,它允许把函数作为一个方法的参数。使用 Lambda 表达式可以使代码更加简洁。在 Java 8 以前,若我们想要把某些功能传递给某些方法,总要去写匿名类。现在用Lambda 表达式,即可以很好地解决问题。

    一、lambda 表达式的语法格式及示范:

    语法:

    (parameters) -> expression
    或
    (parameters) ->{ statements; }

    示范:

    (int a, int b) -> { return a + b; }
    () -> System.out.println("Hello World");
    (String s) -> { System.out.println(s); }
    () -> 42
    () -> { return 3.1415 };

    说明:

    • Lambda 表达式可以具有零个,一个或多个参数。
    • 可以显式声明参数的类型,也可以由编译器根据上下文推断。例如 (int a) 与 (a)等同。
    • 参数用小括号括起来,用逗号分隔。例如 (a, b) 或 (int a, int b) 或 (String a, int b, float c)。
    • 空括号用于表示一组空的参数。例如 () -> 42。
    • 当有且仅有一个参数时,如果不显式指明类型,则不必使用小括号。例如 a -> return a*a。
    • Lambda 表达式的正文可以包含零条,一条或多条语句。
    • 如果 Lambda 表达式的正文只有一条语句,则大括号可不用写,且表达式的返回值类型要与匿名函数的返回类型相同。
    • 如果 Lambda 表达式的正文有一条以上的语句,则必须包含在大括号(代码块)中,且表达式的返回值类型要与匿名函数的返回类型相同。

    二、一个完整的示范

    public class MyDemo {
       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);
       }
       
       public static void main(String args[]) {
          MyDemo tester = new MyDemo();
            
          // 类型声明
          MathOperation addition = (int a, int b) -> a + b;
            
          // 不用类型声明
          MathOperation subtraction = (a, b) -> a - b;
            
          // 花括号中的返回语句
          MathOperation multiplication = (int a, int b) -> { return a * b; };
            
          // 没有花括号及返回语句
          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");
       }
    }

    输出如下:

    %JAVA_HOME%injava "MyDemo" ...
    10 + 5 = 15
    10 - 5 = 5
    10 x 5 = 50
    10 / 5 = 2
    Hello Runoob
    Hello Google

    三、从 Lambda 表达式到双冒号操作符

    使用 Lambda 表达式,可以让代码变得非常简洁。例如,要创建一个比较器,以下语法就足够了:

    Comparator c = (Person p1, Person p2) -> p1.getAge().compareTo(p2.getAge());

    然后,使用类型推断,可以写成如下形式:

    Comparator c = (p1, p2) -> p1.getAge().compareTo(p2.getAge());

    更进一步,可以用如下写法:

    Comparator c = Comparator.comparing(Person::getAge);

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

     四、更多Lambda 表达式的例子

    1. 线程初始化

    // Old way
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Hello world");
        }
    }).start();
    
    // New way
    new Thread(
        () -> System.out.println("Hello world")
    ).start();

    2. 事件处理

    // Old way
    button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Hello world");
        }
    });
    
    // New way
    button.addActionListener( (e) -> {
            System.out.println("Hello world");
    });

    3. 遍历输出(方法引用)

    import java.util.*;
    
    public class MyDemo {
     
       public static void main(String args[]) {
            // Old way
            List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
            for (Integer n : list) {
                System.out.print(n + " ");
            }
            System.out.println();
    
            // 使用 -> 的 Lambda 表达式
            list.forEach(n -> System.out.print(n + " "));
            System.out.println();
    
            // 使用 :: 的 Lambda 表达式
            list.forEach(System.out::print);
       }
    }

    4. 逻辑操作

    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Predicate;
    
    public class MyDemo {
        public static void evaluate(List<Integer> list, Predicate<Integer> predicate) {
            for (Integer n : list) {
                if (predicate.test(n)) {
                    System.out.print(n + " ");
                }
            }
            System.out.println();
        }
    
        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
    
            System.out.print("输出所有数字:");
            evaluate(list, (n) -> true);
    
            System.out.print("不输出:");
            evaluate(list, (n) -> false);
    
            System.out.print("输出偶数:");
            evaluate(list, (n) -> n % 2 == 0);
    
            System.out.print("输出奇数:");
            evaluate(list, (n) -> n % 2 == 1);
    
            System.out.print("输出大于 5 的数字:");
            evaluate(list, (n) -> n > 5);
        }
    
    }

    4. Stream API 示例

    // Old way
    List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
    for(Integer n : list) {
        int x = n * n;
        System.out.println(x);
    }
    
    // New way
    List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
    list.stream().map((x) -> x*x).forEach(System.out::println);

    五、Lambda 表达式和匿名类之间的区别

    • this 关键字。对于匿名类 this 关键字解析为匿名类,而对于 Lambda 表达式,this 关键字解析为包含写入 Lambda 的类。
    • 编译方式。Java 编译器编译 Lambda 表达式时,会将其转换为类的私有方法,再进行动态绑定。

    本文参考:

    https://www.runoob.com/java/java8-lambda-expressions.html

    https://segmentfault.com/a/1190000009186509

  • 相关阅读:
    Visual C++ in Visual Studio 2015
    Paxos
    dtrace
    性能测试应该怎么做?
    CLREX
    Header Field Definitions Accept-Encoding
    汇编跟逆向工程
    Optimize Managed Code For Multi-Core Machines
    Improve Scalability With New Thread Pool APIs
    CLR thread pool
  • 原文地址:https://www.cnblogs.com/nayitian/p/14921035.html
Copyright © 2011-2022 走看看