函数式编程思想概述
:在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿什么东西做什么事情”。相对而言,面向对象过 分强调“必须通过对象的形式来做事情”,而函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是以 什么形式做
lambda表达式的前提:
1. 存在一个接口, 这个接口有且只有一个抽象方法
(有且仅有一个抽象方法的接口,称为“函数式接口”)
( 无论是JDK内置的 Runnable 、 Comparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。 )
(特例:在以下几种情况下,接口不会把其当作是抽象方法,从而符合函数式接口的定义:
–所接口中所定义的方法式默认方法,使用default修饰,有其默认实现。
–方法是静态方法,因为静态方法不能是抽象方法,而是一个已经实现了的方法。
–方法是继承来自 Object 类的public方法,因为任何一个接口或类都继承了 Object 的方法
2. 接口一定要作为方法的参数
(lambda表达式, 只能对匿名内部类的内容进行简写)
标准格式
() : 一些参数
(就写匿名内部类中重写方法的参数列表)
(1. 小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔。)
-> : 一个箭头
(在() 后面写一个箭头, 将小括号中的参数, 给大括号使用)
(2. ->是新引入的语法格式,代表指向动作)
{} : 一段代码
(就写匿名内部类中重写方法的方法体)
(3. 大括号内的语法与传统方法体要求基本一致。)
省略规则
- 小括号中的数据类型, 都可以省略
- 如果小括号中只有一个参数, 数据类型和小括号都可以省略
- 如果大括号中只有一条语句,无论是否有返回值, 大括号, 分号和return都可以省略
例:
Runnable
// 使用匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("开启了一条新线程!~");
}
}).start();
// lambda改进
new Thread(() -> {
System.out.println("开启了一条新线程!~");
}).start();
// 简化格式
new Thread(() -> System.out.println("开启了一条新线程!~")).start();
Comparator
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list, 3, 2, 4, 5, 1);
/*Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) { return o2 - o1; } });*/
// lambda改进
Collections.sort(list, (Integer o1, Integer o2) -> {
return o2 - o1;
});
// 简化格式
Collections.sort(list, (o1, o2) -> o2 - o1);
System.out.println(list);
}
只有一个参数
// 我们要做的是方法的调用
// 匿名内部类
printString(new Printable() {
@Override
public void print(String s) {
System.out.println(s);
}
});
// lambda改进
printString((String s) -> {
System.out.println(s);
});
// 简化格式
printString(s -> System.out.println(s));
System.out.println("你好, Lambda!~");
}
public static void printString(Printable p) {
p.print("你好, Lambda!~");
}
无参无返回
// 调用方法printFood
// 匿名内部类
printFood(new Cook() {
@Override
public void makeFood() {
System.out.println("今天做了, 娃娃菜豆腐汤~");
}
});
// lambda改进
printFood(() -> {
System.out.println("今天做了, 娃娃菜豆腐汤~");
});
// 简化格式
printFood(() -> System.out.println("今天做了, 娃娃菜豆腐汤~"));
}
// 模拟方法
// 方法的参数列表是接口, 那么实际传入的就是该接口的子类对象
public static void printFood(Cook c) {
c.makeFood();
}
}
有参有返回
// 我们实际要写的, 方法的调用
// 匿名内部类
printSum(new Calculator() {
@Override
public int calc(int a, int b) {
return a + b;
}
});
// lambda改进
printSum((int a, int b) -> {
return a + b;
});
// 简化格式
printSum((a, b) -> a + b);
}
// 模拟的方法
public static void printSum(Calculator c) {
System.out.println(c.calc(234, 432));
}
}