Java基础之Lambda表达式
作者:互联网
一、Lambda表达式的介绍
Lambda 表达式Java 8 发布的最重要新特性之一,lambda表达式本质上是一个匿名方法。它允许把函数作为一个方法的参数(函数作为参数传递进方法中)或者把代码看成数据。其优缺点主要有:
优点:
1、使用 Lambda 表达式可以使代码变的更加简洁紧凑;
2、非常容易并行计算;
3、可能代表未来的编程趋势;
缺点:
1、若不用并行计算,很多时候计算速度没有比传统的 for 循环快(CPU单核),并行计算有时需要预热才显示出效率优势;
2、不容易调试;
3、易读性较差,需了解过Lambda 表达式才能看懂;
使用场景
1、函数式接口都可以使用Lambda 表达式;
2、包含复杂数据结构及对象时,可配合Stream进行计算,转化等一系列操作;
Lambda表达式的构造形式:
在最简单的形式中,一个lambda可以参数列表(逗号分隔参数)、–>符号、函数体三部分表示,例如:Predicate p = x ->Integer.parseInt(x)>5;
Lambda表达式的表现形式:
在某些情况下lambda的函数体会比较复杂,这时可以把函数体放到在一对花括号中,就像在Java中定义普通函数一样。表达式可以引用类的成员变量与局部变量(这些变量会被隐含的转为final,目的为了更高的效率)。Lambda表达式式支持有返回值,返回值的类型可由编译器推测出来的,当然如果lambda的函数体只有一行的话,那么没有必要显式使用return语句;
二、函数式接口的介绍
简介:
要想很好地使用lambda表达式,就必须了解函数式接口的概念。函数式接口和普通接口并没有什么不同,唯一的区别在于其接口内部有且只有一个抽象的方法,且需要在接口加上注解(@FunctionalInterface,该注解表明其为函数式接口),像这类的接口就可以被隐式转换为lambda表达式,也就是函数式接口。在实际开发过程中,任何函数式接口都可以使用lambda表达式进行替换,例如:ActionListener、Comparator、Runnable等;
Jdk8常用函数接口:
目前Jdk8自定义的常用函数式接口有Function,Consumer、Supplier、Predicate四大类,其具体详解,可见下表:
接口名称 | 参数 | 用途 |
---|---|---|
Function<T, R> | 入参T,出参R | 主要用于参数转化 |
Consumer<T> | 入参T,无出参 | 主要用于循环迭代,类似于for循环 |
Supplier<T> | 无入参,出参T | 主要于生成特定的参数,包括对象,类似于构造函数 |
Predicate<T> | 入参T,出参boolean型 | 主要用于条件判断,类似于if条件语句 |
Jdk8还有其它的函数式接口,但大多是以以上4大接口衍生而来,当然开发者也可以自己定义函数式接口,但定义函数式接口时,切记接口内部一定有且只有一个抽象方法,且需要加上@FunctionalInterface注解;
三、Lambda表达式的应用举例
3.1、类的静态方法
功能:将字符串整数数字转化整形数字
① 非函数引用
Function<String, Integer> oldFun = new Function<String, Integer>() {
// 注意parseInt方法必须和apply方法的出入参数必须相同
@Override
public Integer apply(String s) {
return Integer.parseInt(s);
}
};
说明:
以上是采用匿名内部类的形式;
② 函数引用
Function<String, Integer> newFun = Integer::parseInt;
说明:
函数引用,其中需要注意的是parseInt方法必须和apply方法的出入参数必须相同(类型),否则将会报错,请参照非函数引用进行理解;
3.2、类的非静态方法
功能:获取学生列表的姓名;
① 非函数引用
@Test
public void test2() {
List<Student> stuList = new ArrayList<>();
stuList.add(new Student("夏侯惇", 31));
stuList.add(new Student("不知火舞", 24));
stuList.add(new Student("孙尚香", 27));
stuList.add(new Student("曹操", 36));
stuList.add(new Student("周瑜", 32));
List<String> stuNameList = stuList.stream().map(new Function<Student, String>() {
@Override
public String apply(Student stu) {
return stu.getName();
}
}).collect(Collectors.toList());
}
说明:
以上是采用匿名内部类的形式,获取列表学生的姓名;
② 函数引用
@Test
public void test2() {
List<Student> stuList = new ArrayList<>();
stuList.add(new Student("夏侯惇", 31));
stuList.add(new Student("不知火舞", 24));
stuList.add(new Student("孙尚香", 27));
stuList.add(new Student("曹操", 36));
stuList.add(new Student("周瑜", 32));
// 非静态方法的函数引用(Student::getName)
List<String> stuNameList = stuList.stream().map(Student::getName).collect(Collectors.toList());
}
说明:
其中getName为Student类的非静态方法,针对非静态方法要使用函数引用,必须满足apply方法的入参为非静态方法的主调者且出参必须与apply方法保持一致(类型),请参照非函数引用进行理解;
3.3、对象引用
功能:获取学生的年龄;
① 非函数引用
@Test
public void test3() {
Student stu = new Student("夏侯惇", 31);
// 非函数引用
Optional<Integer> first = Stream.of(stu).map(new Function<Student, Integer>() {
@Override
public Integer apply(Student stu2) {
return stu.get(stu2);
}
}).findFirst();
}
说明:非函数引用Student对象的年龄;
② 函数引用
Student类的方法
public Integer get(Student stu) {
return stu.getAge();
}
@Test
public void test3() {
Student stu = new Student("夏侯惇", 31);
// apply方法与get方法的出入参数必须相同
Optional<Integer> first = Stream.of(stu).map(stu::get).findFirst();
}
说明:
采用对象引用,但必须满足apply方法与get方法的出入参数相同(类型),请参照非函数引用进行理解;
标签:stuList,Java,函数,接口,Student,new,表达式,Lambda 来源: https://blog.csdn.net/qq_38098851/article/details/104013768