• Lambda表达式、函数式编程思想概述


    Lambda表达式

      y = x + 1,在数学中,函数就是有输入量,输出量的一套计算方案;也就是“拿什么东西,做什么事情”。相对而言,面向对象过程过分强调“必须通过对象的形式来做事情”,而函数式编程思想则尽量忽略面向对象的复杂语法---强调做什么,而不是以什么方式来做。

    面向对象的思想:

      做一件事情,找一个能解决这个事情的对象,调用对象的方法来完成事情。

    函数式编程的思想:

      只要能获得这个事情的结果,谁去做的,怎么做的都不重要,重视的是结果,不重视过程。

    冗余的Runnable代码

      当需要启动一个线程去完成项任务时,通常会通过Runnable接口来定义任务内容,并且使用Thread类来启动线程。

    代码如下:

     public static void main(String[] args) {       
            // 简化代码
    		new Thread(new Runnable() {
    			@Override
    			public void run() {
    				System.out.println(Thread.currentThread().getName() + "----->新线程被创建了!");
    			}
    		}).start();
     }   
    

    函数式编程思想

      强调的是做什么,而不是以什么样的方式来做,它忽略了面向对象的复杂语法,只要能够获取到结果,谁去做的,怎么做的,
    都不重要,重要的是结果,不重视过程。

    冗余的Runnable代码

    传统的写法

    public class Demo01Runnable {
          public static void main(String[] args) {
                //匿名内部类的方式
                      new Thread(new Runnable() {
                            @Override
                            public void run(){
                                  System.out . println("开启了一个新的线程任务");
                            }
                      }).start();//启动新线程
                }
         }
    

    代码分析:

    对于Runnable的匿名内部类用法,可以分析出一下内容:

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

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

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

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

    • 从这里面可以,只有方法体才是线程任务的关键性内容

    以编程思想的转换

    做什么,而不是怎么做

    我们真正希望做的事情是:将run方法体的代码传递给Thread类知晓能够加载到即可。

    传递一段代码---这是我们真正的目的。

    我们需要将程序关注的重点从怎么做回归到做什么,过程和形式并不重要。

    体验Lambda表达式的更优写法

    Java8的新特性,优化刚才的代码

    
    public class Demo01Runnable {
          public static void main(String[] args) {
                //使用Lambda表达式的方式
                new Thread(() -> {
                      System.out.println("开启了一个新的线程任务");
                  }
                ).start();//启动新线程
          }
    }
    

    从上面的代码可以看出:没有创建接口实现类对象的操作,也不再有抽象方法覆盖重写的操作,只写了线程任务的内容。

    从上面的代码能够推导出Lambda的语法:

    () -> System.out.println("开启了一个新的线程任务")
    
    • 前面的一对小括号即run方法, 参数为无,里面是空的,此时需要任何的条件

    • 中间的一个箭头代表将前面的参数传递给后面的代码

    • 后面的输出语句即业务逻辑代码(线程任务内容)

    Lambda的标准格式

    格式由三个部分组成:

    • 一些参数

    • 一个箭头

    • 一段代码

    Lambda表达式的标准格式:

    (参数类型1多数名称1,参数类型2参数名称.... ->{代码语句}
    

    格式说明:

    • 小括号的语法与传统方法参数列表一致,无参数则置空,多个参数则用逗号隔开

    • ->是新引入的语法格式,代表指向的动作

    • 大括号的语法与传统方法体要求基本一致。

    练习:

    定义一段厨子接口,该接口内内置了一个做饭的方法(抽象的方法),且无参数,无返回值,使用Lambda表达式,打印输出“我今天吃的是红烧茄子,吃的好开心”

    public interface Chuzi {
    	//定义一个无参二u返回的方法
    	public abstract void zuofan() ;
    	
    }
    
    public class TestChuzi {
    	
    	  public static void main(String[] args) {
    	    	  
    	    	invokeFood(() -> {
    	    	     System.out.println( "我今天吃的是红烧茄子,吃的好开心");
    	    	  });
    	  }
    	
    	   //定义一个方法, 参数的类型Cook接口,方法内部做- -个调用makeFood()
    	   public static void invokeFood(Chuzi cook) {
    		   cook.zuofan();
    	   }
    
    }
    

    练习2:使用数组存储多个学生对象,对数组中的学生对象使用Arrays的sort方法通过年龄进行升序排序。使用L ambda表达式来实现以上需求。

    public class Student {
    
    	private String name;
    	private Integer age;
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public Integer getAge() {
    		return age;
    	}
    	public void setAge(Integer age) {
    		this.age = age;
    	}
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + "]";
    	}
    	public Student(String name, Integer age) {
    		super();
    		this.name = name;
    		this.age = age;
    	}
    	
    }
    
    //第二个类
    public class Demo01Student{
          public static void main(String[] args){
                //使用数组存储多个学生对象
                Student[] students = {new Student("小孙",20),new Student("小刘",18),new Student("小王",25),new Student("小赵",15)}
                //1.传统的写法 匿名内部类方式
                Arrays.sort(students,new Comparator<>(Student){
                      @Override
                      public int compare(Student s1,Student s2){
                            return s1.getAge()-s2.getAge();
                      }
                });
    
                //2.使用Lambda表达式 简化匿名内部类
                Arrats.sort(students,(Student s1,Student s2)->{
                      return s1.getAge()-s2.getAge(); 
               });
    
                //3.使用Lambda表达式的省略写法
                Arrays.sort(students,(s1,s2)->s1.getAge()-s2.getAge());
    
                for(Student student : students){
                      System.out.println(student);
                }
          }
    }
    

    练习3:给定一个计算器接口, 内置了一个抽象方法计算的方法,可以将两个double类型的数字相加得到和值。使用.ambda表达
    式来实现以上需求。(有参有返回)

    public interface Jisuanj{
          double sum(double a,double b);
    }
    
    public class Jisuan{
          public static void main(String[] args){
                invokeSum(3.14,3.15,(double a,double b)->{
                      return a+b;
                });
          }
          //定义一个方法
    	/*
    	 * 参数传递两个double值,再传递一个接口
    	 * 方法内调用方法
    	 */
          public static void invokeSum(double a,double b,Jisuanj ji){
                double sum = ji.sum(a,b);
                System.out.println("a+b="+sum);
          }
    }
    

    Lambda省略格式

    可推导即可省略

    Lambda强询的是“做什么”,而不是“怎么做”,所以凡是可以根据上下文推导得知的信息,都可以省略。比如:

    invokeSum(3.14, 3.15, (double d1,double d2) -> {
                return d1 + d2;
          });
    //省略格式表达
    invokeSum(3.14,3.15, (d1,d2) -> d1 + d2);
    
    

    省略的规则:

    在Lambda标准格式的表达式的基础上,使用省略写法的规则是:

    1. 小括号内参数的类型可以省略。

    2. 如果小括号内有且只有一个参数,则小括号也可以省略。

    3. 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、retum关键字和语句的分号。

    Lambda的使用前提

    Lambda的语法非常的简洁,使用非常的简单,但是有以下注意事项:

    1. 使用L ambda必须具有接口,且要求接口中有且仅有一个抽象方法
        无论JDK内置的Runnable、Comparator接口还是自定 义的接口,只有当接口中的抽象方法存在且唯一, 才可以使用Lambda

    2. 使用Lambda必须具有上下文推断。
        也就是方法的参数或器局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。

    备注:有且仅有一个抽象方法的接口,称为函数的接口

  • 相关阅读:
    设置IIS允许下载.config文件
    SQL Server 触发器
    MVC参数自动装配
    sql之left join、right join、inner join的区别
    C# 之泛型详解
    Frameset使用教程
    网页引用Font Awesome图标
    ubuntu下apache2 安装 配置 卸载 CGI设置 SSL设置
    深入理解JAVA I/O系列二:字节流详解
    深入理解JAVA I/O系列三:字符流详解
  • 原文地址:https://www.cnblogs.com/luayan/p/14123183.html
Copyright © 2020-2023  润新知