本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1、Lambda介绍
函数式编程,只关心函数!!!
函数式编程守则:
- 函数是“第一等公民”
- 可以赋值给变量
- 可以作为(其他函数的)参数进行传递
- 可以作为(其他函数的)返回值
1.1 Lambda表达式的语法格式
1.2 语法格式细节
1.2.1 可选的大括号{}
解析:函数体只包含一个语句,不需要大括号
// 函数体只包含一个语句,省略大括号`
(String msg) -> System.out.println("hello" + msg);
1.2.2 可选的参数圆括号()
解析:只有一个参数,省略圆括号,同时省略类型
// 只有一个参数,省略圆括号,同时省略类型
msg -> System.out.println("hello "+ msg);
1.2.3 可选的返回关键字return
解析: 函数体只有一个表达式,且运算结果匹配返回类型,可以直接省略return
// 函数体只有一个表达式、省略return
(int a,int b) -> a+b
1.2.4 可选的类型声明
解析: 不需要参数类型,编译器可以根据参数值进行推断
// 省略参数类型,编译器可以进行推断
(a,b) -> a+b;
总结:
- 必须有一个函数式接口,有且只有一个抽象方法的接口 @Functionnallnterface 注解
- 该接口:可以有静态方法,私有方法,Default,有且只有一个抽象方法
2、Lamdba表达式应用举例
常见的函数式接口:
- Runnable/Callable
- Supplier/Consumer
- Comparator
- Predicate
- Function
2.1 Runnable接口
new Thread(()->{
String name = Thread.currentThread().getName();
System.out.println(name + "线程已启动");
}).start();
2.2 Supplier接口
Supplier 接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会产生什么类型的数据
public static void main(String[] args) {
int arr[] = {2, 3, 4, 52, 333, 23};
int max = getMax(() -> {
int mx = arr[0];
for (int i = 1; i < arr.length; i++) {
mx = Math.max(mx, arr[i]);
}
return mx;
});
System.out.println(max);
}
public static int getMax(Supplier<Integer> supplier) {
return supplier.get();
}
2.3 Consumer接口
accept: 这是Consumer功能接口的功能方法。accept方法对给定的参数进行这一操作。
andThen: 此方法返回一个组合的Consumer,该Consumer先执行原始的Consumer操作,然后按照从左到右的顺序执行给定的andThen操作。
public static void main(String[] args) {
consumerString(s -> System.out.println(s));
consumerString(s -> System.out.println(s.toUpperCase()),
s -> System.out.println(s.toLowerCase())
);
}
static void consumerString(Consumer<String> function) {
function.accept("Hello");
}
static void consumerString(Consumer<String> first, Consumer<String> sec) {
first.andThen(sec).accept("Hello");
}
2.4 Predicate接口
对某种数据类型进行判断,结果返回一个Boolean值
public static void main(String[] args) {
andMethod(s->s.contains("W"),s->s.contains("H"));
orMethod(s->s.contains("W"),s->s.contains("H"));
negateMethod(s->s.length()<5);
}
static void andMethod(Predicate<String> one ,Predicate<String> two) {
boolean isValid = one.and(two).test("Helloworld");
System.out.println("字符串符合要求吗:" + isValid);
}
static void orMethod(Predicate<String> one ,Predicate<String> two) {
boolean isValid = one.or(two).test("Helloworld");
System.out.println("字符串符合要求吗:" + isValid);
}
static void negateMethod(Predicate<String> one ) {
boolean isValid = one.negate().test("HelloWorld");
System.out.println("字符串很长吗:" + isValid);
}
2.5 Function接口
Function接口接受一个T类型参数,返回R类型对象或值。
public static void main(String[] args) {
method(s-> Integer.parseInt(s)+10,
s->s*=10);
String str = "周七,28";
int age = getAgeNum(str,s -> s.split(",")[1],s->Integer.valueOf(s),i->i-=10);
System.out.println(age);
}
static void method(Function<String,Integer> one,Function<Integer,Integer> two){
int num = one.andThen(two).apply("10");
System.out.println(num+20);
}
static int getAgeNum(String str,Function<String,String> one
,Function<String,Integer> two
,Function<Integer,Integer> three) {
return one.andThen(two).andThen(three).apply(str);
}
3、方法引用
3.1 为什么需要方法引用?
当Lambda表达式所要完成的业务逻辑已经存在–已经有某个方法实现。我们可以直接引用对应的方法(函数),即方法引用。
3.2 方法引用语法格式
- 双冒号::
3.3 哪些方法可以引用
4、方法引用应用举例
4.1 静态方法引用
保证引用方法与函数式接口抽象方法:参数列表相同,返回值类型相同
public static void main(String[] args) {
// Math类存在静态abs方法,所以直接引用
getNum(Math::abs);
}
static void getNum(Calcable calcable) {
int num = calcable.calsAbs(-10);
System.out.println(num);
}
4.2 构造方法引用
保证引用方法与函数式接口抽象方法:参数列表相同,返回值类型相同
public static void main(String[] args) {
getName(Person::new);
}
static void getName(PersonBuilder personBuilder){
System.out.println(personBuilder.builderPerson("kobe").getName());
}
4.3 普通方法引用
保证引用方法与函数式接口抽象方法:参数列表相同,返回值类型相同
public static void printString(Printable p) {
p.print("HelloWorld");
}
public static void main(String[] args) {
// 非静态方法,需要被对象引用
ObjectMethodReference obj = new ObjectMethodReference();
printString(obj::printUpperCaseString);
}
4.4 类方法引用(super)
保证引用方法与函数式接口抽象方法:参数列表相同,返回值类型相同
public class Man extends Human{
@Override
public void sayHello() {
System.out.println("Hello 我是Man!");
}
// 定义一个方法参数传递Greetable接口
public void method(Greetable g){
g.greet();
}
/**
* super::父类方法名
*/
public void show(){
method(super::sayHello);
}
}
4.5 this方法引用
保证引用方法与函数式接口抽象方法:参数列表相同,返回值类型相同
public void buyHouse (){
System.out.println("北京一套房");
}
public void marry(Richable r){
r.buy();
}
public void soHappy(){
marry(this::buyHouse);
}
4.6 数组的方法引用
# 接口
@FunctionalInterface
public interface ArrayBuilder {
int[] builderArray(int length);
}
public static int[] createArray(int length,ArrayBuilder ab){
return ab.builderArray(length);
}
public static void main(String[] args) {
int[] arr1 = createArray(10,int[]::new);
System.out.println(arr1.length);
}