函数式编程思维概述

在数学中,函数就是有输入量、输出量的一套计算计划,也就是“拿数据做操作”
面向对象思维强调“必须通过对象的模式来做事件”
函数式思维则尽量疏忽面向对象的简单语法:“强调做什么,而不是以什么模式去做”
Lambda表达式就是函数式思维的体现

体验Lambda表达式

需要:启动一个线程,在控制台输入一句话:多线程程序启动了
形式一

  • 定义一个类MyRunnable实现Runnable接口,重写run()办法
  • 创立MyRunnable类的对象
  • 创立Thread类的对象,把MyRunnable的对象作为结构参数传递
  • 启动线程

采纳了实现类的形式实现需求

public class MyRunnable implements Runnable{   private int tickets = 100;   //重写run办法 实现卖票   @Override   public void run(){       sout("多线程程序启动了");   }}   //主程序LambdaDemo//创立MyRunnable对象 MyRunnable my = new MyRunnable();//创立Thread类的对象,把MyRunnable对象作为构造方法的参数Thread t1 = new Thread(my);//启动线程t1.start();

形式二
采纳了匿名外部类形式改良

new Thread(new Runnable(){    @Override    public void run(){       sout("多线程程序启动了");    }}).start();

形式三
采纳了Lambda表达式形式改良

new Thread( () -> {    sout("多线程程序启动了");} ).start();

Lambda表达式的规范格局


Lambda表达式的格局:

  • 格局:(形式参数)->{代码块}
  • 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
  • ->:由英文中画线和大于符号组成,固定写法。代表指向动作
  • 代码块:是咱们具体要做的事件,也就是以前咱们写的办法体内容

    Lambda表达式的练习

    Lambda表达式应用前提

  • 有一个接口
  • 接口中有且仅有一个形象办法

练习1:

形式一
采纳了实现类的形式实现需求

//定义一个接口public interface Eatable{    void eat();//接口中有且仅有一个形象办法}//定义一个类实现这个接口public class EatablleImpl implements Eatable{    @Override    public void eat(){       sout("一天一苹果");    }}//主程序//定义的其中一个办法private static void useEatable(Eatable e){    e.eat();}//在主办法中调用这个办法//创立接口的对象,通过多态的形式Eatable e = new EatablleImpl();useEatable(e);


形式二
采纳了匿名外部类的形式实现需求

useEatable(new Eatable (){    @Override    public void eat(){       sout("一天一苹果");    }});

形式三
采纳了Lambda表达式形式改良

useEatable( () -> {    sout("一天一苹果");} );


练习2:

//定义一个接口public interface Flyable{    void fly(String s);//接口中有且仅有一个形象办法}//主程序//定义的其中一个办法private static void useFlyable(Flyable f){    f.fly(s:"风和日丽");}//在主办法中调用这个办法//创立接口的对象,通过多态的形式Eatable e = new EatablleImpl();useEatable(e);

形式一
采纳了匿名外部类的形式实现需求

useFlyable (new Flyable (){    @Override    public void fly(String s){       sout(s);       sout("飞机自驾游")    }});


形式二
采纳了Lambda表达式形式改良

useFlyable( (String s) -> {   sout(s);   sout("飞机自驾游")} );


练习3:

//定义一个接口public interface Addable{    int add(int x,int y);//接口中有且仅有一个形象办法}//主程序//定义的其中一个办法private static void useAddable(Addable a){    int sum = a.add(x:10,y:10);    sout(sum);}//在主办法中调用这个办法//创立接口的对象,通过多态的形式

采纳了Lambda表达式形式改良

useAddable( (int x,int y) -> {   return x+y;//这是具体的实现 不看办法名,应该看具体的实现} );

Lambda表达式的省略模式

//定义一个接口public interface Addable{    int add(int x,int y);}//定义一个接口public interface Flyable{    void fly(String s);}//测试类useAddable( (int x,int y) -> {   return x+y;//这是具体的实现 不看办法名,应该看具体的实现} );//参数的类型能够省略 然而又多个参数的状况下,不能只省略一个,要么都省略,要么都不省略useAddable( (x,y) -> {   return x+y;//这是具体的实现 不看办法名,应该看具体的实现} );useFlyable( (String s) -> {   sout(s);} );//省略掉类型 useFlyable( (s) -> {   sout(s);} );//如果参数有且仅有一个,小括号也能够省略useFlyable( s -> {   sout(s);} );//如果代码块的语句只有一条,能够省略大括号和分号  如果有return,return也要省略掉,useFlyable( s -> sout(s));//如果有return,return也要省略掉,只针对代码块语句只有一条的状况下useAddable( (x,y) ->  x+y );//定义的其中一个办法private static void useFlyable(Flyable f){    f.fly(s:"风和日丽");}//定义的其中一个办法private static void useAddable(Addable a){    int sum = a.add(x:10,y:10);    sout(sum);}

省略规定:

  • 参数的类型能够省略 然而有多个参数的状况下,不能只省略一个,要么都省略,要么都不省略
  • 如果参数有且仅有一个,小括号也能够省略
  • 如果代码块的语句只有一条,能够省略大括号和分号 如果有return,return也要省略掉

Lambda表达式的注意事项

//定义一个接口public interface Inter{    void show();        //在接口中增加一个办法    //void method();}//定义的其中一个办法 应用这个接口作为参数的办法private static void useInter(Inter i){    i.show();}//主办法的程序//应用Lambda必须要有接口,并且要求接口中有且仅有一个形象办法useFlyable( (String s) -> {   sout("好好学习");} );//化简useFlyable( s -> sout("好好学习") );//应用Lambda必须有上下文环境,能力推导出Lambda对应的接口new Thread(new Runnable(){    @Override    public void run(){       sout("匿名外部类");    }}).start();Runnable r = () -> sout("好好学习");//依据局部变量的类型来推导lambda表达式对应的接口new Thread(r).start();//优化new Thread(() -> sout("好好学习")).start();


注意事项:

Lambda表达式和匿名外部类的区别

//定义一个接口public interface Inter{    void show();}//定义一个类public abstract class Animal{    public abstract void method();//无参无返回值}//定义一个类public class Student{    public void study(){        sout("爱生存");    }}//测试类//在测试类里定义方法调用private static void useStudent(Student s){    s.study();}private static void useAnimal(Animal a){    a.method();}private static void useInter(Inter i){    i.show();}//主函数//先写匿名外部类的useInter (new Inter (){    @Override    public void show(){       sout("接口")    }});useAnimal (new Animal (){    @Override    public void method(){       sout("抽象类")    }});useStudent (new Student (){    @Override    public void study(){       sout("具体类")    }});//用Lambda表达式调用useInter(() -> sout("接口"));useAnimal(() -> sout("抽象类"));//这个报错useStudent(() -> sout("具体类"));//这个也报错

匿名外部类输入

接口中存在多个办法时,应用匿名外部类能够调用办法

Laambda表达式输入

区别