IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> java中Lambda表达式 -> 正文阅读

[Java知识库]java中Lambda表达式

作者:token keyword

1. 为什么要有Lambda表达式?

我们都知道,Lambda表达式是在java1.8引入的新性能,并获得了java开发者的一致好评,那么,java为什么要引入Lambda表达式呢?

1.1 引入前的诉求!

抛开Lambda表达式不说,相信我们在开发中有可能遇到如下情况:

  1. 当你进行Swing开发时,是否使用过Timer定时调用函数?
public Timer(int delay, ActionListener listener){......}

需要一个延迟时间参数和ActionListener 对象,如果没有使用过,没关系,我给个小例子:

package com.mark.spDefault.controller.test;


import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @author:guan
 * @2021/12/7 22:11
 * 文件信息:
 */
public class TestTimer {
    public static void main(String[] args) {
        TimePrinter printer = new TimePrinter();
        Timer timer = new Timer(1000,printer);
        timer.start();
        JOptionPane.showMessageDialog(null,"Quit");
        System.exit(0);
    }
}
class TimePrinter implements ActionListener{

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("我是测试Timer的!");
    }
}

运行结果就是每秒打印一下:我是测试Timer的!

换句话说,就是Timer每秒执行的,就是 System.out.println(“我是测试Timer的!”);这段代码而已!
2. 如果这个比较陌生,我们再举一个例子,我们都知道,java中的sort函数是可以自定义比较器的,例如我们需要按长度给字符串排序:

package com.mark.spDefault.controller.test;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;

/**
 * @author:guan
 * @2021/12/7 22:26
 * 文件信息:
 */
public class TestString {
    public static void main(String[] args) {
        String[] strings = new String[]{"1","22","1111","333"};
        Arrays.sort(strings,new LenghtCom());
        for (String s :strings){
            System.out.println(s);//结果:1 22 333 1111
        }

    }
}
class LenghtCom implements Comparator<String>{
    @Override
    public int compare(String o1, String o2) {
        return o1.length()-o2.length();
    }
}

在sort方法开始运行时,便会调用compare()方法进行比较,实际上,调用的就是compare中的 return o1.length()-o2.length();这段代码。
从上面两个例子,也许你能够发现相似点,就是都是将一段代码传递给了某个对象,第一个例子的Timer,第二个例子的sort方法。这段代码块不会立即调用,而是在未来的某一个时刻调用。

  1. 此时也许你已经发现了问题,java中传递一各代码段太复杂了!!!为了一段代码,我们需要构造一个对象!

2. Lamda简介

由于上面的原因,lamda表达式便提出了,并在java1.8正式引入!

2.1 组成元素

运算符:->
左侧:指定了Lambda表达式所需要的所有参数
右侧:制定了Lambda体,即Lambda表达式所要执行的功能。

话不多说,直接上例子吧,我们前面已经说明了,没有lambda表达式之前,java中传代码段必须要创建对象,那么使用了lambda表达之之后呢?我们来看一下定时器函数:


public class TestTimer {
    public static void main(String[] args) {
//        lambda表达式
        Timer timer = new Timer(1000,(event)-> System.out.println("我是测试Timer的Lambda版本!"));
        timer.start();
        JOptionPane.showMessageDialog(null,"Quit");
        System.exit(0);
    }
}

看到差别了吗?一句话就能搞定,其中->左侧能够看到,有一个参数event,有人会说,这里后面就一个打印语句,也没有用到参数event啊,可以删除吗?这是不可以的哈!!!具体原因我们后面再分析。下面来看一下第二个sort函数使用lambda表达式之后是什么样:

public class TestString {
    public static void main(String[] args) {
        String[] strings = new String[]{"1","22","1111","333"};
        Arrays.sort(strings,(s1,s2)->{return s1.length()-s2.length();});
        for (String s :strings){
            System.out.println(s);
        }
    }
}

怎么样?很方便吧!这里同样的,有两个参数,而且还有返回值,我们接下来聊一下参数问题哈!

2.2 lambda表达式中的参数问题

我们还是先看上面那两个例子哈,在没替换之前,我们是怎么搞的?那定时器那个为例:是不是要先定义一个TimerPrinter对象,然后将这个对象传到定时器里:如下TimePrinter 对象:

class TimePrinter implements ActionListener{

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("我是测试Timer的!");
    }
}

我们再来仔细看一下这个对象,里面实现了一个方法,actionPerformed(ActionEvent e),前面也已经说了,传递给定时器的,就是方法中的这段打印信息的代码,我们现在使用Lambda表达式来完成同样的任务,是不是就要和这个方法对应呢?即:

  1. 参数对应,这里有个参数,那对应的lambda表达式也要有对应的参数。
  2. 方法为void,那对应的lambda表达式就不需要有return返回值。

到这里,其实就大致能看出,在定时器这里的lambda表达式,其实就是实现了ActionListener中的actionPerformed方法,我们可以debug以下:
设置断点如下:

断点设置
在listenerList中我们能够看到其中一个listener是我们定义的lambda生成的!
在这里插入图片描述
同样的,我们在sort排序中,是不是在没有使用lambda表达式之前创建了一个LenghtCom对象,该对象实现了Comparator接口,并重写了一个public int compare(String o1, String o2)方法,注意了哈,这里这个方法是有返回值的,int类型的,并且有两个String类型的参时。那么,同样的,在我们实现的Lambda表达式中,

 Arrays.sort(strings,(s1,s2)->{return s1.length()-s2.length();});

同样有两个参数s1和s2,和一个return返回值为int。这里s1和s2你也可以带上String声明,就类似如下:

Arrays.sort(strings,(String s1,String s2)->{return s1.length()-s2.length();});

都是没关系的,lambda在特定情况下能够智能推断出你的参数类型,所以这里不加String声明也可以正常运行。

3 如何定义一个可以使用lambda表达式的对象?

讲到这里,相信大家对lambda表达式已经有一定的了解了,但是是不是所有的对象方法都可以使用lambda表达式呢?答案肯定是否定的,不信你可以试试!!!那什么时候可以用呢?或者说,如何定义一个可以使用lambda表达式的对象方法呢?别着急,我这就介绍!!!

3.1 函数式接口

在自定义可以使用lambda表达式的方法时,需要先搞清楚什么是函数式接口,这点特别重要,不过也很容易理解。
函数式接口:只有一个抽象方法的接口。
怎么样?很容易理解吧?比如下面这个接口:

public interface TestConsumer {

    void accept(int value);
}

对喽,这就是一个函数式接口!!!

3.2 自定义函数式接口测试lambda表达式

现在,我们就可以测试接口了,就用TestConsumer 这个接口为例吧!
现在编写测试类:

package com.mark.spDefault.controller.test;

/**
 * @author:guan
 * @2021/12/7 17:23
 * 文件信息:
 */
public class testLambda {
    public static void repeat(int n,TestConsumer testConsumer){
        for (int i=0;i<n;i++){
            testConsumer.accept(i);
        }
    }
    public static void main(String[] args) {
    }
}

testLambda类里有一个类方法:repeat,里面循环调用TestConsumer 接口的accept()函数。
现在我们写main函数:

public static void main(String[] args) {

        repeat(10,new TestConsumer() {
            @Override
            public void accept(int value) {
                System.out.println("test");
            }
        });
    }

正常情况下调用repeat()函数必须new一个TestConsumer对象并实现方法accept(),类似于下面这样:

public static void main(String[] args) {

        repeat(10,new TestConsumer() {
            @Override
            public void accept(int value) {
                System.out.println("test");
            }
        });
    }

但是现在有了lambda表达式,我们可以直接像下面这样:如果你使用的是idea,能够看到提示:
在这里插入图片描述

哈哈哈,点一下就成下面这样了

public static void main(String[] args) {

        repeat(10, value -> System.out.println("test"));
    }

在这里插入图片描述
可以运行一下试试!

好,先讲到这里,后面还有命名规则,参数规则以及和stream结合使用lambda表达式,后面会一一介绍!

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 15:35:19  更:2021-12-11 15:36:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:49:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码