《疯狂java讲义》学习(51):Lambda表达式

本文详细介绍了Java 8的Lambda表达式,包括通过接口传递代码、Lambda语法、函数式接口、预定义的函数式接口如Predicate、Function和Consumer的使用示例,以及方法引用和函数的复合。此外,还提供了Java实例练习——凯撒密码的加密解密实现。
摘要由CSDN通过智能技术生成

Lambda表达式

Lambda这个名字来源于学术界的λ演算,具体我们就不探讨了。理解Lambda表达式,我们需要先回顾一下接口、匿名内部类和代码传递。

通过接口传递代码

我们之前介绍过接口以及面向接口的编程,针对接口而非具体类型进行编程,可以降低程序的耦合性,提高灵活性,提高复用性。接口常被用于传递代码,比如,我们知道File有如下方法:

public File[] listFiles(FilenameFilter filter)

listFiles需要的其实不是FilenameFilter对象,而是它包含的如下方法:

boolean accept(File dir, String name);

或者说,listFiles希望接受一段方法代码作为参数,但没有办法直接传递这个方法代码本身,只能传递一个接口。
再如,类Collections中的很多方法都接受一个参数Comparator,比如:

public static <T> void sort(List<T> list, Comparator<? super T> c)

他们需要的也不是Comparator对象,而是它包含的如下方法:

int compare(T o1, T o2);

但是,没有办法直接传递方法,只能传递一个接口。
又如,异步任务执行服务ExecutorService,提交任务的方法有:

<T> Future<T> submit(Callable<T> task);
Future<? > submit(Runnable task);

Callable和Runnable接口也用于传递任务代码。
通过接口传递行为代码,就要传递一个实现了该接口的实例对象,在之前的章节中,最简洁的方式是使用匿名内部类,比如:

//列出当前目录下的所有扩展名为.txt的文件
File f = new File(".");
File[] files = f.listFiles(new FilenameFilter(){
   
    @Override
    public boolean accept(File dir, String name) {
   
        if(name.endsWith(".txt")){
   
            return true;
        }
        return false;
    }
});

将files按照文件名排序,代码为:

Arrays.sort(files, new Comparator<File>() {
   
    @Override
    public int compare(File f1, File f2) {
   
        return f1.getName().compareTo(f2.getName());
    }
});

提交一个最简单的任务,代码为:

ExecutorService executor = Executors.newFixedThreadPool(100);
executor.submit(new Runnable() {
   
    @Override
    public void run() {
   
        System.out.println("hello world");
    }
});

Lambda语法

Java 8提供了一种新的紧凑的传递代码的语法:Lambda表达式。对于前面列出文件的例子,代码可以改为:

File f = new File(".");
File[] files = f.listFiles((File dir, String name) -> {
   
    if(name.endsWith(".txt")) {
   
        return true;
    }
    return false;
});

可以看出,相比匿名内部类,传递代码变得更为直观,不再有实现接口的模板代码,不再声明方法,也没有名字,而是直接给出了方法的实现代码。Lambda表达式由->分隔为两部分,前面是方法的参数,后面{}内是方法的代码。上面的代码可以简化为:

File[] files = f.listFiles((File dir, String name) -> {
   
    return name.endsWith(".txt");
});

当主体代码只有一条语句的时候,括号和return语句也可以省略,上面的代码可以变为:

File[] files = f.listFiles((File dir, String name) -> name.endsWith(".txt"));

注意:没有括号的时候,主体代码是一个表达式,这个表达式的值就是函数的返回值,结尾不能加分号,也不能加return语句。
方法的参数类型声明也可以省略,上面的代码还可以继续简化为:

File[] files = f.listFiles((dir, name) -> name.endsWith(".txt"));

之所以可以省略方法的参数类型,是因为Java可以自动推断出来,它知道listFiles接受的参数类型是FilenameFilter,这个接口只有一个方法accept,这个方法的两个参数类型分别是File和String。这样简化下来,代码是不是简洁多了?
排序的代码用Lambda表达式可以写为:

Arrays.sort(files, (f1, f2) -> f1.getName().compareTo(f2.getName()));

提交任务的代码用Lambda表达式可以写为:

executor.submit(()->System.out.println("hello"));

参数部分为空,写为()。
当参数只有一个的时候,参数部分的括号可以省略。比如,File还有如下方法:

public File[] 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值