开篇废话: 在数学中,函数就是有输入量、输出量的一套计算方案,也就是“那什么东西做什么事情” 面向对象过分强调“必须通过对象的形式来做事情” 函数式思想则尽量忽略面向对象的复杂语法–强调做什么,而不是以什么形式做
方式思想面向对象做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情函数式编程思想只要能获取到结果,谁去做,怎么做都不重要,忠实的是结果,不重视过程我们从北京到上海,可以选择如上图任意种方式。 但是我们真正的目的是到达上海,而如何才能到达上海的形式并不重要,所以我们一直在探索有没有比高铁更好地方式:飞机
而现在这种飞机(甚至是飞船)已经诞生:2014年3月Oracle 所发布的Java 8(JDK1.8)中,加入了Lambda表达式的重量级新特性,为我们打开了新世界的大门从线程的实现方式中,我们采用了匿名内部类,但是仍存在代码的冗余,此时需要引入Lambda(只为了目的,不考虑过程)
↓ Runnable接口实现类代码:
public class RunnableImpl implements Runnable { public void run() { System.out.println("执行线程体"); } }↓ 主线程代码:
public class ThreadLambda { public static void main(String[] args) { RunnableImpl runnable = new RunnableImpl(); Thread thread = new Thread(runnable); thread.start(); // ========================= 优化 ========================= // 匿名内部类写法 Runnable r = new Runnable() { public void run() { System.out.println("第一次优化"); } }; new Thread(r).start(); // ========================= 优化 ========================= // 匿名内部类写法 new Thread(new Runnable() { public void run() { System.out.println("第二次优化"); } }).start(); } }Lambda 更优写法
↓ 从匿名内部类,去掉冗余优化成Lambda表达式:
public class ThreadLambda2 { public static void main(String[] args) { // ========================= 优化 ========================= new Thread(new Runnable() { public void run() { System.out.println("第二次优化"); } }).start(); // 使用Lambda 表达式,实现多线程 new Thread(() -> { System.out.println("kkk"); }).start(); } }Lambda省去面向对象的条条框框,格式由3部分组成
一些参数一个箭头一段代码Lambda表达式的标准格式为:
(参数类型 参数名称)-> { 代码语句}格式说明:
小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则使用逗号分隔->是新引入的语法格式,代表指向动作大括号内的语法与传统方法体要求基本一致↓ 代码实现:
public class InvokeCook { public static void main(String[] args) { // 嗲用invokeCook 方法,参数是Cook接口,传递Cook接口的匿名内部类对象 invokeCook(new Cook(){ @Override public void makeFood() { System.out.println("吃饭啦"); } }); // 使用Lambda 标准格式 调用 invokeCook方法 invokeCook(()->{ System.out.println("吃饭啦(Lambda)"); }); } private static void invokeCook(Cook cook){ cook.makeFood(); } }需求: 使用数组存储过个Person对象 对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序
↓ 实体类 Person 代码如下:
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public Person() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }↓ main 主线程 代码如下:
public class ArraysLambda { public static void main(String[] args) { // 使用数组存储过个Person对象 Person[] arr = { new Person("CTRA", 2), new Person("lily", 3), new Person("katy", 6), }; // 对数组中的Person对象使用Arrays的sort方法通过年龄进行升序(前边-后边)排序 // Arrays.sort(arr, new Comparator<Person>() { // @Override // public int compare(Person o1, Person o2) { // return o1.getAge()-o2.getAge(); // } // }); // 使用lambda表达式,简化匿名内部类 Arrays.sort(arr,(Person o1, Person o2)->{ return o1.getAge()-o2.getAge(); }); for (Person person : arr) { System.out.println(person); } } }需求: 给定一个计算器Caculator接口,内含抽象方法calc可以将俩个int数字相加得到和值 使用Lambda的标准格式调用invokeCalc 方法,完成120和130相加计算
↓ 计算器Caculator接口,代码实现:
public interface Caculator { int Caculator(int a ,int b); }↓ main主线程方法,分别使用:匿名内部类、Lambda表达式的方式来实现需求:
public class CaculLambda { public static void main(String[] args) { // 首先使用 匿名内部类 invokeCalc(140,120,new Caculator(){ @Override public int Caculator(int a, int b) { return a+b; } }); // 使用Lambda表达式 invokeCalc(140,120,(int a, int b)->{ return a+b; }); } // 使用Lambda的标准格式调用invokeCalc public static void invokeCalc(int a, int b,Caculator c) { int sum = c.Caculator(a,b); System.out.println("相加的值:"+sum ); } }Lambda强调的是“做什么”而不是“怎么做”,所以凡是可以根据上下文推导得知的信息,都是可以忽略的。 如上Lambda代码可以省略的写法: ↓ 原代码:
// 使用Lambda表达式 invokeCalc(140,120,(int a, int b)->{ return a+b; });↓ 再次省略的代码:
invokeCalc(140, 120, (a, b) -> a + b);在Lambda标准格式的基础上,使用省略写法的规则为:
小括号内参数的类型可以省略如果小括号内有且仅有一个参数,小括号可以省略如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号,return关键字及语句分号