Java8新特性——Lambda表达式(一)

1. 预备知识

在了解Lambda表达式之前首先需要了解以下预备知识。

1.1 如何成为一名高级码农?

如果老板让你写一个用于毁灭地球的函数,而你写了一个毁灭行星的函数,若要毁灭地球只需将毁灭地球的过程传递给“毁灭行星”。能做到这一点,你就是一名高级码农。

以上这个问题体现了程序可扩展性的思想。总结一下,要成为一名高级码农,在编码的时候要以发展的眼光看待问题。一个具体问题到来的时候,你需要基于当前问题抽象出解决这一类问题的办法,那么当相似的问题到来时,你只需花少量的时间就能完成任务,而且避免了代码复制,降低了bug的风险。

1.2 实现程序可扩展性的例子

在Java8以前,要实现程序的可扩展性,我们常用匿名内部类传递用于扩展的代码,举个例子:

实现一个能从List集合中筛选指定对象的函数filter。 1. 若List中存放Person对象,要求筛选出30岁以上的Person 2. 若List中存放Apple,要求筛选出红色的Apple

使用匿名内部类的解决方案:

  • 实现filter函数
List<T> filter(List<T> list, FilterProcessor filterProcessor){
    List<T> result = new ArrayList<T>();
    for(T t : list){
        if(filterProcessor.process(t))
            result.add(t);
    }
    return list;
}
  • 定义FilterProcessor接口
interface FilterProcessor<T>{
    boolean process(T);
}
  • 使用匿名内部类实现筛选出30岁以上的Person
List<Person> result = filter(list, new FilterProcessor<Person>(){
    boolean process(Person person){
        if(person.getAge()>=30)
            return true;
        return false;
    }
});
  • 使用匿名内部类筛选出红色的Apple
List<Apple> result = filter(list, new FilterProcessor<Apple>(){
    boolean process(Apple apple){
        if(apple.getColor().equals("red"))
            return true;
        return false;
    }
});

若要增加新的筛选规则,只需给filter函数传递新的匿名内部类即可。程序具有了可扩展性,恭喜你已经成为一名高级码农!

1.3 什么是“策略模式”?

上述过程总结来说,当我们需要解决同一类问题的时候,若发现这类问题大部分处理过程是一致的,只是核心步骤存在差异,这时候就可以使用上述方式:先把函数相同的部分写好,再抽象出一个接口,不同部分的代码放在接口的实现类中。要使用时,只需将实现类的对象传递给该函数即可。 这种方式在设计模式中称为“策略模式”。

1.4 使用匿名内部类实现策略模式的弊端?

使用匿名内部类实现策略模式代码比较冗余,不易阅读,就像这样:

List<Apple> result = filter(list, new FilterProcessor<Apple>(){
    boolean process(Apple apple){
        if(apple.getColor().equals("red"))
            return true;
        return false;
    }
});

Java8提出了Lambda表达式,它是实现策略模式的另外一种方式,目的就是为了使代码简单清晰。 使用Lambda表达式实现相同功能:

List<Apple> result = filter(list, (Apple apple)—>apple.getColor().equals("red"));

这样是不是简单多了!Lambda表达式本质上是将一个函数的代码作为一个参数或变量进行传递,这种处理方式有个专门的名字——函数式编程。

1.5 什么是函数式编程?

所谓“函数式”编程,就是将函数的代码当作一个变量,传递给另一个变量或传递给一个函数,这种编程方式就称为“函数式编程”。 Java8中采用Lambda表达式实现函数式编程,它是策略模式的第二种实现方式,目的就是简化策略模式的代码实现。

2. Lambda表达式的语法

Lambda表达式用于表示一个函数,所以它和函数一样,也拥有参数、返回值、函数体,但它没有函数名,所以Lambda表达式相当于一个匿名函数。语法如下:

(Person person)—>person.getAge()>30

Lambda表达式用—>连接,->左侧为函数的参数,->右侧为函数体。 若右侧由多条语句构成则需要用{}包裹,如:

(Person person)—>{person.getAge()>30;System.out.println(person.getName());}

Lambda表达式无需显示指定返回值类型,JVM会根据->右侧语句的返回结果自动判断返回值类型,如:

(Person person)—>person.getAge()>30 #自动判断返回值为boolean型

3. 如何使用Lambda表达式?

仍以筛选年龄大于30的Person对象为例:

3.1 为Lambda表达式定义函数式接口

@FunctionalInterface
interface FilterProcessor<T>{
    boolean process(T t);
}

PS:该接口只能有一个抽象函数!接下来Lambda表达式就是该抽象函数的实现。 PS:在为Lambda表达式定义函数式接口时,需要加上注解@FunctionalInterface,这样当该接口中抽象函数个数不是1时就会报错提示。

3.2 实现筛选函数

List<T> filter(List<T> list, FilterProcessor<T> filterProcessor){
    List<T> result = new ArrayList<T>();
    if(filterProcessor.process(t))
        result.add(t);
    return result;
}

filter函数接收一个函数式接口,该参数用于接收一个Lambda表达式。

3.3 传递Lambda表达式

List<Person> result = filter(list, (Person p)->p.getAge()>30);

直接将Lambda表达式作为参数传递给filter的函数式接口即可,从而在result中就能获取年龄超过30岁的Person对象。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端知识分享

第195天:js---函数对象详解(call、apply)

853
来自专栏Play & Scala 技术分享

挑逗 Java 程序员的那些 Scala 绝技

有个问题一直困扰着 Scala 社区,为什么一些 Java 开发者将 Scala 捧到了天上,认为它是来自上帝之吻的完美语言;而另外一些 Java 开发者却对它...

1166
来自专栏Spark学习技巧

分段锁的原理

1612
来自专栏Java技术栈

跟我学 Java 8 新特性之 Stream 流基础体验

Java8新增的功能中,要数lambda表达式和流API最为重要了.这篇文章主要介绍流API的基础,也是流API系列的第一篇文章,话不多说,直奔主题.

1013
来自专栏Java技术栈

switch case 支持的 6 种数据类型!

1484
来自专栏程序你好

Java和c++构造函数的区别是什么?

如果你是一个c++程序员,现在正在学习Java,你会发现这两种流行的面向对象编程语言有很多相似之处。这两种语言都支持抽象、封装、类、对象和其他OOP概念。但是,...

564
来自专栏海天一树

小朋友学C++(7):封装

面向对象有三个特征:封装、继承和多态。 本节主要讲解封装。 所有的 C++ 程序都有以下两个基本要素: 函数:这是程序中执行动作的部分,它们被称为函数或方法。 ...

27110
来自专栏java一日一条

Java 容器相关知识全面总结

Java实用类库提供了一套相当完整的容器来帮助我们解决很多具体问题。因为我本身是一名Android开发者,包括我在内很多安卓开发,最拿手的就是ListView(...

391
来自专栏禁心尽力

多线程编程:多线程并发制单的开发记录【一】

进程和线程: 下图是在来自知乎用户的解释,个人感觉狠到位 ?        进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资...

1977
来自专栏青青天空树

java多重转型问题

  这个程序中涉及了三次类型转换,该行为紧密依赖于转型的符号拓展行为。Java使用了基于2的补码的二进制运算,因此int类型的-1用32位补码表示就是11111...

682

扫码关注云+社区