zoukankan      html  css  js  c++  java
  • 躲不掉的 lambda 表达式

    lambda 表达式是 Java8 的新特性,虽说都发布很久了,但是不到万不得已是肯定不会研究这个的,现在就是那不得不学习的时候了。

    本文主要说一下什么 lambda 表达式、Java 中为什么要有 lambda 表达式以及 lambda 表达式的应用。

    在 Java 面向对象的思想中,我们知道函数是不能单独存在的,函数一般会作为某个对象的功能封装在对象之中,我们传递参数也不能传递一个函数。曾经 Java 也为此挣扎过,我们看下面这段代码,创建一个线程,输出一句话。

    new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Hello World !");
                }
            }).start();

    有点基础应该都知道这是匿名内部类,但是你知道的,真正有效的代码就一行输出语句。其余代码基本没用,我们可以反过来想一下,我们创建线程是为了执行某一个任务,也就是某一个方法,那我们为何不直接传入一个方法呢?

    按照这个思路,我们可以这样写伪代码。

    new Thread((某某任务)).start();

    好了,现在问题就出现了,如何去形容这个任务,或者说在 Java 中如何表示呢?lambda 表达式应运而生。

    一个函数,可能会有入参,函数要有函数体,于是就这样定义了 lambda 表达式 “(参数1,参数2)-> { 函数体 } ” 。

    但是吧,实际使用过程中,因为参数和函数体的不同,又有一些变种的写法,一个 lambda 表达式可以有零个或多个参数,参数之间用逗号相隔。空括号代表参数为空。

    lambda 表达式的主体可包含零条或多条语句,如果 lambda 表达式的主体只有一条语句,花括号 { } 可省略,否则必须包含在花括号 { } 中。

    OK,到这里我们就可以重写上面的线程了。

    new Thread(
                () -> System.out.println("Hello World ")
              ).start();

    说到这简单回忆一下什么是 lambda 表达式,曾经 Java 中不能直接把函数做参数,为了能行,创造了 lambda 表达式,可以把 lambda 表达式理解为一个功能块,只不过匿名罢了。

    其实 lambda 的出现是为了和函数式编程相呼应,函数式编程,就是用函数为主体来编程,把函数当成是代码的基本组成部分,就像变量一样。官方说法叫第一等公民。

    举个例子说明一下函数式编程的特点。

    计算如下表达式:
    (1 + 2) * 3 - 4
    
    传统的过程式编程,可能这样写(比较傻,为了演示效果):
    int a = 1 + 2;
    int b = a * 3;
    int c = b - 4;
    
    函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,然后写成下面这样:
    int result = subtract(multiply(add(1,2), 3), 4);

    有点蒙,没关系,先理解 lambda 表达式的使用再说,lambda 表达式最常用的莫过于替换 Runnable 接口实现线程任务,还有什么用处呢?

    太难的不介绍,说一个比较简单的,用于列表的迭代。

    对一个列表的每一个元素进行操作,不使用 Lambda 表达式时如下:

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    for (int element : numbers) {
        System.out.prinln(element);
    }

    使用 Lambda 表达式:

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    numbers.forEach(x -> System.out.println(x));

    重点在操作上,输入是 x ,然后对 x 进行输出操作。就线程和列表迭代来说,为什么他们能接收 lambda 表达式作为参数呢?我们看看 forEach 方法的参数内部是什么。

     * @since 1.8
     */
    @FunctionalInterface
    public interface Consumer<T> {
    
        /**
         * Performs this operation on the given argument.
         *
         * @param t the input argument
         */
        void accept(T t);

    是一个接口,而这个接口被定义为函数式接口,lambda 表达式可以替换功能接口,我们就来自定义一个函数式接口来演示一下。

    定义一个函数式接口:

    // 定义一个功能接口或叫函数式接口
    @FunctionalInterface
    public interface WorkerInterface {
        // 该接口中只能有一个抽象方法
        public void doSomeWork();
    }
    
    public class WorkerInterfaceTest {
    
        public static void execute(WorkerInterface worker) {
            worker.doSomeWork();
        }
    
        public static void main(String[] args) {
    
            // invoke doSomeWork using Annonymous class
            execute(new WorkerInterface() {
                @Override
                public void doSomeWork() {
                    System.out.println("Worker invoked using Anonymous class");
                }
            });
            // invoke doSomeWork using Lambda expression
            execute(()->{System.out.println("Worker invoked using Lambda expression");});
        }
    }

    总结一下最开始提出的几个问题,lambda 表达式可以理解为是一个匿名的函数,我们可以通过 lambda 表达式来代替功能接口(比方说 Runnable 接口)。函数式编程是一种编程模式,Java 为了支持它而定义了 lambda 。lambda 的应用主要在替代功能接口,列表迭代,还有一些对集合的操作上。

    最后,能告诉我你现在使用 Lambda 表达式了吗,都是用在什么地方呢 ?

  • 相关阅读:
    jQuery 中 attr() 和 prop() 方法的区别
    Jquery DOM元素的方法
    超链接的#和javascript:void(0)的区别
    CSS定位之position详解(转载)
    jQuery最佳实践(转载)
    jQuery官方基础教程笔记(转载)
    股票---基金基础知识
    eclipse里面构建maven项目详解(转载)
    sax解析操作XML
    DOM4j操作xml文件
  • 原文地址:https://www.cnblogs.com/YJK923/p/10536560.html
Copyright © 2011-2022 走看看