Java Lambda 表达式

文章介绍了Java8引入的Lambda表达式,它用于简化代码,特别是处理函数式接口。Lambda表达式由->分隔参数和实现,可以省略参数类型、括号和return语句。函数式接口是只有一个抽象方法的接口,Lambda可与其结合使用。文章还讨论了方法引用的概念,允许直接使用方法名代替Lambda表达式,并展示了构造方法引用的例子。
摘要由CSDN通过智能技术生成

Lambda 表达式是 Java 8 提供的一种语法,主要用来替代匿名内部类,传递函数式接口代码。

函数式接口:只有一个抽象方法的接口,还允许定义静态方法和默认方法。

基本语法

Lambda 表达式由 -> 分隔为两部分,前面是方法的参数部分,后面 {} 内是方法的实现代码。

import java.io.File;

public class Test1 {

    public static void main(String[] args) {
        File file = new File(".");

        File[] fileArr = file.listFiles((File dir, String name) -> {
            return null != name && name.endsWith(".txt");
        });
    }

}

当主体代码只有一条语句的时候,{} 括号 和 return 语句 可以省略。

此时,主体代码是一个表达式,表达式的值就是函数的返回值,结尾不能加分号 ;,也不能加 return 语句。

import java.io.File;

public class Test1 {

    public static void main(String[] args) {
        File file = new File(".");

        File[] fileArr = file.listFiles((File dir, String name) -> null != name && name.endsWith(".txt"));
    }

}

方法的参数类型声明也可以省略。

File file = new File(".");

File[] fileArr = file.listFiles((dir, name) -> null != name && name.endsWith(".txt"));

当参数只有一个的时候,参数部分的括号可以省略,参数为空或者多个的时候,括号不能省略。

File file = new File(".");

File[] files = file.listFiles(path -> path.getName().endsWith(".txt"));

Lambda 表达式通过推断的方式实现,与匿名内部类相似,它可以访问定义在主体代码外部的变量,对于局部变量,只能访问 final 类型的变量或者事实上只赋值一次的变量赋值。

File file = new File(".");
String msg = "消息";

File[] files = file.listFiles(path -> {
	System.out.println(msg);
	return path.getName().endsWith(".txt");
});

Java 会为每个匿名内部类生成一个类,但 Lambda 表达式不会生成类,也不会引入接口,不用担心会生成太多类的问题。

函数式接口

函数式接口:只有一个抽象方法的接口,还允许定义静态方法和默认方法。都有一个注解:@FunctionalInterface 。

Lambda 表达式可以赋值给函数式接口。

FileFilter filter = path -> path.getName().endsWith(".txt");

FilenameFilter fileNameFilter = (dir, name) -> name.endsWith(".txt");

Java 8 在 java.util.function 包中定义了大量的预定义函数式接口,用于常见类型的代码传递。
在这里插入图片描述

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Test1 {

    public static void main(String[] args) {
        List<Student> students = Arrays.asList(new Student[]{
                new Student("张三", 89),
                new Student("李四", 94),
                new Student("王五", 90)
        });

        students = filter(students, t -> t.getScore() >= 90);

        for (Student student: students) {
            System.out.println(student.name + ":" + student.getScore());
        }
    }

    public static<E> List<E> filter(List<E> list, Predicate<E> pred) {
        List<E> retList = new ArrayList<>();
        for(E ele : list) {
            if (pred.test(ele)) {
                retList.add(ele);
            }
        }
        return retList;
    }

}

class Student {
    String name;
    double score;

	public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public Student(String name, double score) {
        this.name = name;
        this.score = score;
    }
}

方法引用

Lambda 表达式经常用于调用对象的某个方法,比如:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

public class Test1 {

    public static void main(String[] args) {
        List<Student> students = Arrays.asList(new Student[]{
                new Student("张三", 89),
                new Student("李四", 94),
                new Student("王五", 90)
        });

        List<String> names = getNameList(students, t -> t.getName());

        for(String name: names) {
            System.out.println(name);
        }
    }

    public static<T, R> List<String> getNameList(List<T> list, Function<T, R> mapper) {
        List<String> retList = new ArrayList<>(list.size());
        for(T ele : list){
            retList.add((String) mapper.apply(ele));
        }
        return retList;
    }
}

class Student {
    String name;
    double score;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public Student(String name, double score) {
        this.name = name;
        this.score = score;
    }

    public static String getCollegeName(){
        return "xxx School";
    }
}

对于 List<String> names = getNameList(students, t -> t.getName());,可以进一步简化:

List<String> names = getNameList(students, Student::getName);

形如 Student::getName 称为方法引用,由 :: 分隔为两部分,前面是类名或变量名,后面是方法名。

当 Lambda 表达式的操作仅仅是调用某个存在的方法时,可以使用方法引用。

此外,方法引用的方法的参数类型和返回值类型必须和接口一致。

  • 类名::类方法名
Supplier<String> s1 = () -> Student.getCollegeName();
Supplier<String> s2 = Student::getCollegeName;
  • 类名::实例方法名

在调用实例作为参数传入时使用。

Function<Student, String> f1 = (Student t) -> t.getName();
Function<Student, String> f2 = Student::getName;
  • 实例名::实例方法名
for (Student student: students) {
    Supplier<String> s2 = () -> student.getName();
    Supplier<String> s1 = student::getName;
}
  • 构造方法引用

对于构造方法,方法引用的语法是 <类名>::new,比如:Student::new。

BiFunction<String, Double, Student> s1 = (name, score) -> new Student(name, score);
BiFunction<String, Double, Student> s2 = Student::new;
IntFunction<int[]> arrayMaker = int[]::new;
int[] array = arrayMaker.apply(10) // 创建数组 int[10]

参考:《Java 编程的逻辑》马俊昌

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值