zoukankan      html  css  js  c++  java
  • Java8函数式编程以及Lambda表达式

    第一章 认识Java8以及函数式编程

    关注公众号(CoderBuff)回复“stream”获取《Java8 Stream编码实战》PDF完整版。

    《Java8 Stream编码实战》的代码全部在https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/stream-coding,一定要配合源码阅读,并且不断加以实践,才能更好的掌握Stream。

    尽管距离Java8发布已经过去7、8年的时间,但时至今日仍然有许多公司、项目停留在Java7甚至更早的版本。即使已经开始使用Java8的项目,大多数程序员也仍然采用“传统”的编码方式。

    即使是在Java7就已经有了处理异常的新方式——try-with-resources,但大多数程序员也仍然采用在finally语句中关闭相应的资源。

    我认为Java8和Java5的意义同等重要,Java5的众多新特性使得Java正式迈入编程界的统治地位。同样,Java8的发布,也使得这一门“古老”的语言具备了更加现代化的特性。

    Java8最为引入瞩目就是支持函数式编程

    如果说面向对象编程是对数据的抽象,那么函数式编程就是对行为的抽象[1]

    button.addActionListener(new ActionListener() { 
            public void actionPerformed(ActionEvent event) {
                System.out.println("button clicked");
            }
    });
    
    以上示例来自于《Java 8函数式编程》

    这个示例是为了一个按钮增加一个监听,当点击这个按钮时,将会触发打印“button clicked”行为。

    在Java支持函数式编程以前,我们如果需要传递一个行为常用的方式就是传递一个对象,而匿名内部类正是为了方便将代码作为数据进行传递。

    当然,函数式编程,并不是在Java8中才提出来的新概念,

    函数式编程属于编程范式中的一种,它起源于一个数学问题。我们并不需要过多的了解函数式编程的历史,要追究它的历史以及函数式编程,关于范畴论、柯里化早就让人立马放弃学习函数式编程了。

    对于函数式编程我们所要知道的是,它能将一个行为传递作为参数进行传递。至于其他的,就留给学院派吧。

    第二章 Lambda表达式

    在第一章的示例中,我们看到在以前想要传递一个行为,我们通常使用的是匿名内部类,而从Java8开始,引入了一种全新更为简洁的方式来支持函数式编程,那就是——Lambda表达式。

    我们把第一章中的示例改为Lambda作为本章的开始。

    button.addActionListener(event -> System.out.println("button clicked"));
    

    Lambda表达式语法规则主体分为两个部分,中间用“->”右箭头连接,左边代表参数,右边代表函数主体。

    2.1 函数式接口

    在Java中有一个接口中只有一个方法表示某特定方法并反复使用,例如Runnable接口中只有run方法就表示执行的线程任务。

    Java8中对于这样的接口有了一个特定的名称——函数式接口。Java8中即使是支持函数式编程,也并没有再标新立异另外一种语法表达。所以只要是只有一个方法的接口,都可以改写成Lambda表达式。在Java8中新增了java.util.function用来支持Java的函数式编程,其中的接口均是只包含一个方法。

    例如Predicate接口中只包含test方法,该函数接口接受一个输入参数,返回一个布尔值。

    函数式接口中的方法可以有参数、无参数、有返回值、无返回值。

    • () -> System.out.println("hellobug"),表示无参数。

    • event -> System.out.println("hellobug"),表示只有一个参数。

    • (x, y) -> {System.out.println(x); System.out.println(y);},表示两个参数,可以不必指定参数类型,为了更清楚地表达意图,最好还是加上参数类型,(String x, String y) -> {System.out.println(x); System.out.println(y);}

    接下来我们来编写一个带参数且有返回的函数式接口

    package com.coderbuff.chapter2_lambda.function;
    
    /**
     * 函数式接口
     * @FunctionalInterface 注解只是为了表明这是一个函数式接口,函数式接口只能包含一个方法。
     * @author okevin
     * @date 2020/3/14 23:32
     */
    @FunctionalInterface
    public interface FunctionalInterfaceDemo {
        boolean test(Integer x);
    }
    
    com.coderbuff.chapter2_lambda.function.FunctionalInterfaceDemo

    除了@FunctionalInterface注解,其它和一个普通的接口无任何差别。@FunctionalInterface注解只是为了标注这是一个函数式接口,如果标注了@FunctionalInterface注解,此时接口中就只能包含一个方法,因为函数式接口只能包含一个方法。

    接着我们在测试类中编写一个方法,方法的参数就是这个函数式接口,这代表了我们将传递行为

    package com.coderbuff.chapter2_lambda.function;
    
    /**
     * 按匿名类的方式使用一个函数式接口,传递行为
     * @author okevin
     * @date 2020/3/14 23:42
     */
    public class AnonymousInnerClassTest {
    
        private void testAnonymousInnerClass(FunctionalInterfaceDemo functionalInterfaceDemo) {
            Integer number = 1;
            boolean result = functionalInterfaceDemo.test(number);
            System.out.println(result);
        }
    }
    
    com.coderbuff.chapter2_lambda.function.AnonymousInnerClassTest

    testAnonymousInnerClass方法的含义表示将通过FunctionalInterfaceDemo#test方法判断传入的参数1返回布尔值。

    我们应该如何通过Lambda表达式来使用这个函数式接口呢?

    前面我们说了,这个参数代表了我们将传递一个行为,这个行为决定了1返回是true还是false,我们先通过匿名内部类实现这个接口。

    package com.coderbuff.chapter2_lambda.function;
    
    /**
     * 按匿名类的方式使用一个函数式接口,传递行为
     * @author okevin
     * @date 2020/3/14 23:42
     */
    public class AnonymousInnerClassTest {
    
        private void testAnonymousInnerClass(FunctionalInterfaceDemo functionalInterfaceDemo) {
            Integer number = 1;
            boolean result = functionalInterfaceDemo.test(number);
            System.out.println(result);
        }
    
        public static void main(String[] args) {
            AnonymousInnerClassTest anonymousInnerClassTest = new AnonymousInnerClassTest();
    
            anonymousInnerClassTest.testAnonymousInnerClass(new FunctionalInterfaceDemo() {
                @Override
                public boolean test(Integer x) {
                    if (x > 1) {
                        return true;
                    }
                    return false;
                }
            });
        }
    }
    

    这是在Java8之前通过匿名内部类实现行为的传递,在有了Lambda表达式后,通过上文的Lambda表达式语法规则,这是一个参数+一个返回(Lambda表达式中有返回值时return可以省略),并且有多行代码。

    anonymousInnerClassTest.testAnonymousInnerClass(number -> {
        if (number > 1) {
            return true;
        }
        return false;
    });
    

    关注公众号(CoderBuff)回复“stream”抢先获取PDF完整版。

    近期教程:

    《ElasticSearch6.x实战教程》

    《Redis5.x入门教程》

    《Java8 编码实战》

    这是一个能给程序员加buff的公众号 (CoderBuff)

    1. 《On Java 8》 ↩︎

  • 相关阅读:
    520了,用32做个简单的小程序
    年轻就该多尝试,教你20小时Get一项新技能
    自定义注解!绝对是程序员装逼的利器!!
    vs2015添加ActiveX Control Test Container工具(转载)
    编译MapWinGis
    C#遍历集合与移除元素的方法
    c#winform程序,修改MessageBox提示框中按钮的文本
    java程序员面试答题技巧
    什么是DOM
    uml类关系
  • 原文地址:https://www.cnblogs.com/yulinfeng/p/12552786.html
Copyright © 2011-2022 走看看