函数式编程思维概述
在数学中,函数就是有输入量、输出量的一套计算计划,也就是“拿数据做操作”
面向对象思维 强调“必须通过对象的模式来做事件”
函数式思维 则尽量疏忽面向对象的简单语法:“强调做什么,而不是以什么模式去做”
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 表达式输入
区别