Java 8 函数式编程基础:Lambda表达式与四大函数式接口以及方法引用详解
1 Lambda表达式
Lambda表达式是Java 8及更高版本中引入的一个关键特性,它提供了一种编写匿名函数(即没有名称的函数)的简洁方式。Lambda表达式可以传递给函数式接口(Functional Interface)的实例,函数式接口是只包含一个抽象方法的接口(可以包含多个默认方法或静态方法,但只能有一个抽象方法)。
1.1 Lambda表达式的基本语法如下:
(parameters) -> expression
或
(parameters) ->{ statements; }
parameters 是参数列表,expression 或 { statements; } 是Lambda 表达式的主体。如果只有一个参数,可以省略括号;如果没有参数,也需要空括号。
1.2 Lambda表达式写法:
使用一个->符号,箭头将Lambda表达式分为左右两部分,左边写的是实现的这个接口中的抽象方法中的形参列表,右边就是对抽象方法的处理;
1.3 Lambda 表达式的结构:
Lambda表达式不是万能的,他需要函数式接口的支持;@FunctionalInterface 注解,可以检查它是否是一个函数式接口;
1.3.1以RunnAble接口举例:
原本的使用方法:
//继承Runnable
public class MyRunAble implements Runnable{
@Override
public void run() {
System.out.println("-----");
}
}
}
//测试类
public class Test03 {
public static void main(String[] args) {
MyRunAble myRunAble=new MyRunAble();
Thread thread=new Thread(myRunAble);
thread.start()
}
}
//运行结果如下:
-----
Lambda表达式:
public static void main(String[] args) {
//lambda表达式
Runnable runnable1 = () -> {
System.out.println("-----");
};
Thread thread1=new Thread(runnable1);
thread1.start();
}
}
//运行结果如下:
-----
可以省略方法名,IDEA会帮你自动检测方法名;—上述省略的是runnable接口中run()方法
如果对抽象方法的实现逻辑只有一行,可以省略方法体的大括号,当然如果不止一行,就不能省略了;
//一行运行代码,{}可以省略
Runnable runnable2 = () -> System.out.println("-----");
1.3.2自定义接口举例:
interface test{
int fun(Integer a);
}
测试:
//一个参数时()可以省略
//一行运行代码,有返回值时,{}可以省略 ,同时return省略
test t = a -> a;
System.out.println(t.fun(5));
可以省略方法中的形参类型;形参列表中只有一个参数,可以去掉形参的括号;有返回值的方法,如果要去掉大括号,还需要去掉return关键字;
//Lambda表达式也可以作为参数传递
//此时匿名函数是Runnable
Thread thread = new Thread(() -> {
System.out.println("线程执行");
});
2 Java中四大函数式接口
Consumer
代表了一个接受单个输入参数并且不返回任何结果的操作。
常用于执行某些操作,比如打印日志、发送消息等。
import java.util.function.Consumer;
public class ConsumerExample {
public static void main(String[] args) {
// 使用Lambda表达式创建Consumer实例
Consumer
// 调用accept方法执行操作
printer.accept("Hello, Consumer!");
}
}
Supplier
代表了一个供应者,它不接受任何参数,并返回单个结果。
常用于生成或检索单个值。
import java.util.function.Supplier;
public class SupplierExample {
public static void main(String[] args) {
// 使用Lambda表达式创建Supplier实例,该实例每次调用get方法时返回相同的值
Supplier
// 调用get方法获取值
System.out.println(supplier.get()); // 输出: 42
}
}
Function
接受一个输入参数T,并返回一个结果R。
下面是Function接口示例:
import java.util.function.Function;
public class FunctionExample {
public static void main(String[] args) {
// 使用Lambda表达式创建Function实例,将String转换为大写String
Function
// 调用apply方法执行转换
String original = "hello, world!";
String transformed = toUpperCase.apply(original);
// 输出转换后的结果
System.out.println(transformed); // 输出: HELLO, WORLD!
}
}
Predicate
代表一个断言型接口,它接受一个输入参数T,并返回一个布尔值结果。
常用于条件判断。
import java.util.function.Predicate;
public class PredicateExample {
public static void main(String[] args) {
// 使用Lambda表达式创建Predicate实例,检查字符串是否为空
Predicate
// 调用test方法执行判断
System.out.println(isEmpty.test("")); // 输出: true
System.out.println(isEmpty.test("not empty")); // 输出: false
}
}
3 方法引用
方法引用其实是Lambda表达式的另一种写法,当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用;方法引用通过方法的名字来指向一个方法。方法引用可以使语言的构造更紧凑简洁,减少冗余代码。方法引用使用一对冒号 :: 。
3.1 Java中主要有四种类型的方法引用:
静态方法引用:通过类名来引用静态方法。
语法:类名::静态方法名
示例:Integer::parseInt 引用Integer类的parseInt(String s)静态方法。
对象的实例方法引用:通过特定对象来引用实例方法。
语法:对象::实例方法名
注意:这种类型的方法引用不太常用,因为Lambda表达式通常用于传递无状态的操作,而特定对象的引用通常包含状态。
特定类型的任意对象的实例方法引用:通过类名来引用该类型任意对象的实例方法。Lambda表达式的第一个参数会成为调用该方法的对象。
语法:类名::实例方法名
示例:String::length 引用String类中任意对象的length()实例方法。
构造方法引用:通过类名来引用构造方法。
语法:类名::new
示例:ArrayList::new 引用ArrayList类的构造方法。
3.2 示例
第一种 类名::静态方法名
①自定义一个学生对象:两个属性name和score并提供了初始化name和score的构造方法,并且在最下方提供了两个静态方法分别按score和name进行比较先后顺序。
public class Student {
private String name;
private int score;
public Student(){
}
public Student(String name,int score){
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public static int compareStudentByScore(Student student1,Student student2){
return student1.getScore() - student2.getScore();
}
public static int compareStudentByName(Student student1,Student student2){
return student1.getName().compareToIgnoreCase(student2.getName());
}
}
②按着分数由小到大排列并输出:
Student student1 = new Student("a",20);
Student student2 = new Student("b",70);
Student student3 = new Student("c",80);
Student student4 = new Student("d",90);
List
//先使用lambda表达式的方式进行处理
//sort方法接收一个Comparator函数式接口,接口中唯一的抽象方法compare接收两个参数返回一个int类型值
students.sort((o1, o2) -> o1.getScore() - o2.getScore());
students.forEach(student -> System.out.println(student.getScore()));
//Comparator接口定义
@FunctionalInterface
public interface Comparator
int compare(T o1, T o2);
}
//上述Student类中定义的compareStudentByScore静态方法
public static int compareStudentByScore(Student student1,Student student2){
return student1.getScore() - student2.getScore();
}
//发现同样是接收两个参数返回一个int类型值,而且是对Student对象的分数进行比较,所以我们这里就可以 使用类名::静态方法名 方法引用替换lambda表达式
students.sort(Student::compareStudentByScore);
students.forEach(student -> System.out.println(student.getScore()));
第二种 对象::实例方法名
自定义一个StudentComparator类
public class StudentComparator{
public int compareStudentByScore(Student student1,Student student2){
return student2.getScore() - student1.getScore();
}
}
//发现该方法的定义满足Comparator接口的compare方法定义,所以这里可以直接使用 对象::实例方法名 的方式使用方法引用来替换lambda表达式
//Comparator
//students.sort((o1, o2) -> o1.getScore() - o2.getScore());
StudentComparator studentComparator = new StudentComparator();
students.sort(studentComparator::compareStudentByScore);
students.forEach(student -> System.out.println(student.getScore()));
第三种 类名::实例方法名
一定是lambda表达式所接收的第一个参数来调用实例方法,如果lambda表达式接收多个参数,其余的参数作为方法的参数传递进去。
//在Student类中加入一个方法
public int compareByScore(Student student){
return this.getScore() - student.getScore();
}
//Comparator
//students.sort((o1, o2)-> o1.compareByScore(o2));
//类名::实例方法名
students.sort(Student::compareByScore);
students.forEach(student -> System.out.println(student.getScore()));
第四种 类名::new
Supplier函数式接口的get方法,不接收参数有返回值,正好符合无参构造方法的定义
@FunctionalInterface
public interface Supplier
/**
* Gets a result.
*
* @return a result
*/
T get();
}
//使用了Student类构造方法引用创建了supplier实例,以后通过supplier.get()就可以获取一个Student类型的对象,前提是Student类中存在无参构造方法。
Supplier
接下来我们将真正开始学习stream ,请看下篇:
随便看看
- 2025-10-19 18:41:13《魔兽世界》wcl分数查看方法介绍
- 2025-04-23 02:36:00塔塔大作战·2025春日光耀庆典:全服集结挑战暗影之塔限时活动
- 2025-10-12 23:36:25如何在iPhone上设置自动开关机:详细步骤和注意事项
- 2025-10-17 07:40:10亚洲荣光! “时光机”带你回顾在亚洲举办的世界杯赛|图解体育
- 2025-05-11 17:44:282025年5月11日《乱斗之王》全球狂欢盛典:巅峰对决,荣耀加冕!
- 2025-04-19 08:52:55五行降妖师:天地异变·五行归一限时觉醒全服庆典活动
- 2025-07-16 10:26:10彼界:时空裂隙·终焉回响——2025跨次元觉醒庆典
- 2025-09-28 22:16:38包邮真假美猴王
- 2025-06-13 23:37:592025年6月13日切菜狂人全球挑战赛:成为最速切菜达人!
- 2025-03-29 02:38:23《圣战传说》史诗级跨服巅峰对决——2025荣耀试炼之战限时开启!
