本文是Lambda的入门文章。主要向读者介绍Lambda的基本概念和写法。主要面向的读者是Java新手。

 主要内容:

  • Lambda到底是什么东西?
  • 怎么通过Lambda简化代码?

 

背景知识:其中在逐步推导Lambda表达式时,需要用到并发编程中的Runnable接口。

目录

什么是Lambda

第一个Lambda表达式

原始写法

静态内部类简化

局部内部类简化

匿名内部类简化

Lambda简化

再简化

Lambda实例


基本特性:

  1. 是JDK1.8开始之后的新技术,是一种代码的新语法。
  2. 目的是为了简化匿名内部类的代码写法

使用前提:

  1. 首先必须是接口。
  2. 接口中只能有一个抽象方法。
  3. 即,Lambda表达式只能简化接口中只有一个抽象方法的匿名内部类形式。

函数式接口:

  1. 接口中只有一个抽象方法的接口称为函数式接口。
  2. 函数式接口注解:@FunctionalInterface 一旦某个接口加上了这个注解,这个接口只能、有且仅有一个抽象方法。

Lambda 语法

  1. (params) -> expression
  2. (params) -> statement
  3. (params) -> { statements }
  4. 左侧:Lambda 表达式的参数列表;右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体

在并发编程中,我们可以通过实现Runnable接口来开辟一个新的任务线程。下面,通过任务线程的代码编写,来理解Lambda是如何简化写法的。

首先明确,Runnable接口只有一个方法,满足函数式接口的条件:

以下是常规的写法:

  1. public class Main {
  2. public static void main(String[] args) {
  3. Thread thread = new Thread(new MyThread()); //创建一个线程
  4. thread.start(); //执行线程
  5. }
  6. }
  7.  
  8. //实现Runnable接口,实现任务线程
  9. class MyThread implements Runnable {
  10. @Override
  11. public void run() {
  12. System.out.println("线程"+Thread.currentThread().getName()+"执行了!");
  13. }
  14. }

  

将线程任务类放在要调用内的内部,作为静态内部类或者成员内部类:

  1. public class Main {
  2. //实现Runnable接口,实现任务线程
  3. public static class MyThread implements Runnable {
  4. @Override
  5. public void run() {
  6. System.out.println("线程"+Thread.currentThread().getName()+"执行了!");
  7. }
  8. }
  9.  
  10. public static void main(String[] args) {
  11. Thread thread = new Thread(new MyThread()); //创建一个线程
  12. thread.start(); //执行线程
  13. }
  14. }

  

把任务线程放在方法体内、局部变量的位置:

  1. public class Main {
  2. public static void main(String[] args) {
  3. class MyThread implements Runnable { //局部内部类,就相当于申明一个变量
  4. @Override
  5. public void run() {
  6. System.out.println("线程"+Thread.currentThread().getName()+"执行了!");
  7. }
  8. }
  9.  
  10. Thread thread = new Thread(new MyThread()); //创建一个线程
  11. thread.start(); //执行线程
  12. }
  13. }

  

省略实现类类名的方式,其中“new Runnable() {}”,等价于“class 名字 implements Runnable() {}”:

  1. public class Main {
  2. public static void main(String[] args) {
  3. Thread thread = new Thread(new Runnable() {
  4. @Override
  5. public void run() {
  6. System.out.println("线程"+Thread.currentThread().getName()+"执行了!");
  7. }
  8. }); //申明任务线程
  9.  
  10. thread.start(); //执行线程
  11. }
  12. }

  

Lambda的简化格式:

   (匿名内部类被重写方法的形参列表) -> {

       被重写方法的方法体代码。

   }

Lambda简化:

  1. public class Main {
  2. public static void main(String[] args) {
  3.  
  4. //使用Lambda简化:
  5. // 把"public void run()"简化为"()"。
  6. // 之所以不用指定方法名,是因为函数式接口中有且仅有一个方法,只要一调用,只有那一个方法可以调用
  7. // 方法体保持不变
  8. Thread thread = new Thread( () -> {
  9. System.out.println("线程"+Thread.currentThread().getName()+"执行了!");
  10. });
  11. thread.start();
  12. }
  13. }

  

  1. 再简化:
  2. public class Main {
  3. public static void main(String[] args) {
  4. //方法体内只有一行代码,可以直接去掉方法体的花括号:{}
  5. Thread thread = new Thread(() -> System.out.println("线程"+Thread.currentThread().getName()+"执行了!") );
  6. thread.start();
  7. }
  8. }
  9.  
  10.  
  11. 匿名对象的简化:
  12. public class Main {
  13. public static void main(String[] args) {
  14. //把Thread类转换为匿名对象
  15. new Thread(() -> System.out.println("线程"+Thread.currentThread().getName()+"执行了!")).start();
  16. }
  17. }

  

Lambda简化Comparator接口匿名内部类写法:

  1. public static void main(String[] args) {
  2. List<Student> lists = new ArrayList<>();
  3. Student s1 = new Student("李铭",18,'男');
  4. Student s2 = new Student("冯龙",23,'男');
  5. Student s3 = new Student("王乐乐",21,'男');
  6. Collections.addAll(lists , s1 , s2 , s3);
  7.  
  8. // 按照年龄进行升序排序!
  9. Collections.sort(lists, new Comparator<Student>() {
  10. @Override
  11. public int compare(Student s1, Student s2) {
  12. return s1.getAge() - s2.getAge();
  13. }
  14. });
  15.  
  16. // Lambda简化写法
  17. Collections.sort(lists, (Student t1, Student t2) -> {
  18. return t1.getAge() - t2.getAge();
  19. });
  20. // 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写。
  21. // 此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
  22. Collections.sort(lists,(Student t1, Student t2) -> t1.getAge() - t2.getAge());
  23.  
  24. // 参数类型可以省略
  25. Collections.sort(lists, (t1, t2) -> t1.getAge() - t2.getAge());
  26.  
  27. System.out.println(lists);
  28. }

  

forEach遍历简化

  1. public static void main(String[] args) {
  2. List<String> names = new ArrayList<>();
  3. names.add("胡伟光");
  4. names.add("甘挺");
  5. names.add("洪磊");
  6.  
  7. //forEach遍历原理
  8. names.forEach(new Consumer<String>() {
  9. @Override
  10. public void accept(String s) {
  11. System.out.println(s);
  12. }
  13. });
  14.  
  15. //Lambda简化
  16. names.forEach((String s) -> {
  17. System.out.println(s);
  18. });
  19.  
  20. //省略入参类型
  21. names.forEach((s) -> {
  22. System.out.println(s);
  23. });
  24. //如果只有一个参数,省略:入参括号
  25. names.forEach(s -> {
  26. System.out.println(s);
  27. });
  28.  
  29. //Lambda表达式的方法体代码只有一行代码,省略花括号、分号
  30. names.forEach(s -> System.out.println(s) );
  31.  
  32. names.forEach(System.out::println);
  33. }

  

总结:

  • Lambda的作用是简化代码的写法,减少代码量。
  • 核心语法是:(参数1,参数2) -> { 方法体(如果方法体可以使用一句代码,则可以省略花括号) }

版权声明:本文为qishun原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/qishun/p/14393409.html