Java中Lambda表达式使用及详解

2023-05-16

Java中Lambda表达式使用及详解



前言


一、Lambda表达式的简介

Lambda表达式(闭包):java8的新特性,lambda运行将函数作为一个方法的参数,也就是函数作为参数传递到方法中。使用lambda表达式可以让代码更加简洁。

Lambda表达式的使用场景:用以简化接口实现。

关于接口实现,可以有很多种方式来实现。例如:设计接口的实现类、使用匿名内部类。 但是lambda表达式,比这两种方式都简单。

package test;

/**
 * @author: Mercury
 * Date: 2022/3/20
 * Time: 17:48
 * Description:Lambda表达式
 * Version:1.0
 */
public class Test04 {
    public static void main(String[] args) {
        //使用lambda表达式实现接口
        Test test = () -> {
            System.out.println("test");
        };
        test.test();
    }
}

interface Test{
    public void test();
}

二、Lambda表达式对接口的要求

虽然说,lambda表达式可以在⼀定程度上简化接口的实现。但是,并不是所有的接口都可以使用lambda表达式来简洁实现的。

lambda表达式毕竟只是⼀个匿名方法。当实现的接口中的方法过多或者多少的时候,lambda表达式都是不适用的。

lambda表达式,只能实现函数式接口。

1.函数式接口

如果说,⼀个接口中,要求实现类必须实现的抽象方法,有且只有⼀个!这样的接口,就是函数式接口。

代码如下(示例):

//有且只有一个实现类必须要实现的抽象方法,所以是函数式接口
interface Test{
    public void test();
}

2.@FunctionalInterface

是⼀个注解,用在接口之前,判断这个接口是否是⼀个函数式接口。 如果是函数式接口,没有任何问题。如果不是函数式接口,则会报错。功能类似于 @Override。
代码如下(示例):

@FunctionalInterface
interface Test{
    public void test();
}

3.Lambda表达式的语法

1.Lambda表达式的基础语法

lambda表达式,其实本质来讲,就是⼀个匿名函数。因此在写lambda表达式的时候,不需要关心方法名是什么。

实际上,我们在写lambda表达式的时候,也不需要关心返回值类型。

我们在写lambda表达式的时候,只需要关注两部分内容即可:参数列表和方法体

lambda表达式的基础语法:
(参数1,参数2,…) -> {
方法体
};

参数部分:方法的参数列表,要求和实现的接口中的方法参数部分⼀致,包括参数的数量和类型。

方法体部分 : 方法的实现部分,如果接口中定义的方法有返回值,则在实现的时候,注意返回值的返回。

-> : 分隔参数部分和方法体部分。

代码示例:

package test;

/**
 * @author: Mercury
 * Date: 2022/3/20
 * Time: 17:48
 * Description:Lambda表达式
 * Version:1.0
 */
public class Test04 {
    public static void main(String[] args) {
        //使用lambda表达式实现接口

        //无参
//        Test test = () -> {
//            System.out.println("test");
//        };

        //有参
//        Test test = (name,age) -> {
//            System.out.println(name+age+"岁了!");
//        };
//        test.test("小新",18);

        //有参+返回值
        Test test = (name,age)  -> {
            System.out.println(name+age+"岁了!");
            return age + 1;
        };
        int age = test.test("小新",18);
        System.out.println(age);

    }
}

//无参
//interface Test{
//    public void test();
//}

//有参 无返回值
//interface Test{
//    public void test(String name,int age);
//}

//有参 有返回值
interface Test{
    public int test(String name,int age);
}

4.Lambda表达式的语法进阶

参数部分的精简

参数的类型

由于在接口的方法中,已经定义了每⼀个参数的类型是什么。而且在使用lambda表达式实现接口的时候,必须要保证参数的数量和类 型需要和接口中的方法保持⼀致。因此,此时lambda表达式中的参数的类型可以省略不写。

注意点:

如果需要省略参数的类型,要保证:要省略, 每⼀个参数的类型都必须省略不写。绝对不能出现,有的参数类型省略了,有的参数类型没有省略。

        //有参+返回值
        Test test = (name,age)  -> {
            System.out.println(name+age+"岁了!");
            return age + 1;
        };
        int age = test.test("小新",18);
        System.out.println(age);

参数的小括号

如果方法的参数列表中的参数数量 有且只有⼀个,此时,参数列表的小括号是可以省略不写的。

注意事项:

  • 只有当参数的数量是⼀个的时候, 多了、少了都不能省略。
  • 省略掉小括号的同时, 必须要省略参数的类型
        //一个参数
        Test test = name -> {
            System.out.println(name+"test");
        };
        test.test("小新");

方法体部分的精简

方法体⼤括号的精简

当⼀个方法体中的逻辑,有且只有⼀句的情况下,⼤括号可以省略

Test test = name -> System.out.println(name+"test");
        test.test("小新");

return的精简

如果⼀个方法中唯⼀的⼀条语句是⼀个返回语句, 此时在省略掉大括号的同时, 也必须省略掉return。

Test test = (a,b) -> a+b;

三、函数引用

lambda表达式是为了简化接口的实现的。在lambda表达式中,不应该出现比较复杂的逻辑。如果在lambda表达式中出现了过于复杂的逻辑,会对程序的可读性造成非常大的影响。如果在lambda表达式中需要处理的逻辑比较复杂,⼀般情况会单独的写⼀个方法。在lambda表达式中直接引用这个方法即可。

函数引用:引用⼀个已经存在的方法,使其替代lambda表达式完成接口的实现

1.静态方法的引用

语法:类::静态方法

注意事项:

  • 在引用的方法后面,不要添加小括号。
  • 引用的这个方法,参数(数量、类型)和返回值,必须要跟接口中定义的⼀致
package test;

/**
 * @author: Mercury
 * Date: 2022/3/20
 * Time: 18:17
 * Description:lambda表达式静态方法引用
 * Version:1.0
 */
public class Test05 {
    public static void main(String[] args) {
        //实现多个参数,一个返回值的接口
        //对一个静态方法的引用,语法:类::静态方法
        Test1 test1 = Calculator::calculate;
        System.out.println(test1.test(4,5));
    }
}

class Calculator{
    public static int calculate(int a,int b ){
        // 稍微复杂的逻辑:计算a和b的差值的绝对值
        if (a > b) {
            return a - b;
        }
        return b - a;
    }
}

interface Test1{
    int test(int a,int b);
}

2.非静态方法的引用

语法:对象::非静态方法

注意事项:

  • 在引用的方法后⾯,不要添加小括号。
  • 引用的这个方法, 参数(数量、类型) 和 返回值, 必须要跟接口中定义的⼀致。
package test;

/**
 * @author: Mercury
 * Date: 2022/3/21
 * Time: 8:14
 * Description:lambda表达式对非静态方法的引用
 * Version:1.0
 */
public class Test06 {
    public static void main(String[] args) {
        //对非静态方法的引用,需要使用对象来完成
        Test2 test2 = new Calculator()::calculate;
        System.out.println(test2.calculate(2, 3));
    }
    private static class Calculator{
        public int calculate(int a, int b) {
            return a > b ? a - b : b - a;
         }
    }
}
interface Test2{
    int calculate(int a,int b);
}

3.构造方法的引用

使用场景

如果某⼀个函数式接口中定义的方法,仅仅是为了得到⼀个类的对象。此时我们就可以使用构造方法的引用,简化这个方法的实现。

语法:类名::new

注意事项:可以通过接口中的方法的参数, 区分引用不同的构造方法。

package com.cq.test;

/**
 * @author: Mercury
 * Date: 2022/4/27
 * Time: 10:31
 * Description:lambda构造方法的引用
 * Version:1.0
 */
public class Test {
    private static class Dog{
        String name;
        int age;
        //无参构造
        public Dog(){
            System.out.println("一个Dog对象通过无参构造被实例化了");
        }
        //有参构造
        public Dog(String name,int age){
            System.out.println("一个Dog对象通过有参构造被实例化了");
            this.name = name;
            this.age = age;
        }
    }
    //定义一个函数式接口,用以获取无参的对象
    @FunctionalInterface
    private interface GetDog{
        //若此方法仅仅是为了获得一个Dog对象,而且通过无参构造去获取一个Dog对象作为返回值
        Dog test();
    }

    //定义一个函数式接口,用以获取有参的对象
    @FunctionalInterface
    private interface GetDogWithParameter{
        //若此方法仅仅是为了获得一个Dog对象,而且通过有参构造去获取一个Dog对象作为返回值
        Dog test(String name,int age);
    }

    // 测试
    public static void main(String[] args) {
        //lambda表达式实现接口
        GetDog lm = Dog::new; //引用到Dog类中的无参构造方法,获取到一个Dog对象
        Dog dog = lm.test();
        System.out.println("修狗的名字:"+dog.name+" 修狗的年龄:"+dog.age); //修狗的名字:null 修狗的年龄:0
        GetDogWithParameter lm2 = Dog::new;//引用到Dog类中的有参构造,来获取一个Dog对象
        Dog dog1 = lm2.test("萨摩耶",2);
        System.out.println("修狗的名字:"+dog1.name+" 修狗的年龄:"+dog1.age);//修狗的名字:萨摩耶 修狗的年龄:2

    }
}

四、Lambda表达式需要注意的问题

这⾥类似于局部内部类、匿名内部类,依然存在闭包的问题。

如果在lambda表达式中,使用到了局部变量,那么这个局部变量会被隐式的声明为 final。是⼀个常量,不能修改值。


总结

以上就是Lambda表达式相关内容,本文仅简单介绍了Lambda表达式的使用,祝各位小伙伴们学习愉快,欢迎交流!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java中Lambda表达式使用及详解 的相关文章

随机推荐

  • 树莓派 | 解决VNC Viewer无法连接显示问题

    如果觉得本篇文章对您的学习起到帮助作用 xff0c 请 点赞 43 关注 43 评论 xff0c 留下您的足迹 x1f4aa x1f4aa x1f4aa VNC Viewer是一个很不错的远程桌面应用 xff0c 但是我们在树莓派中使用时
  • kubeadm部署k8s,coredns一直处于containercreating状态failed to find plugin “flannel“ in path [/opt/cni/bin]]

    问题 xff1a coredns始终处于containercreating状态 coredns镜像拉取不下来 xff0c 只能手动拉去之后修改tag进行解决这个问题 xff0c 具体步骤如下 xff1a span class token n
  • Docker Compose部署Springboot+Mysql项目

    声明 xff1a 本文CSDN作者原创投稿文章 xff0c 未经许可禁止任何形式的转载 xff0c 原文链接 在上一篇文章Spring Boot Maven 43 Docker打包中 xff0c 我们实现了将Springboot项目源代码一
  • 华为交换机配置LACP模式链路聚合

    文章目录 1 拓扑图2 任务描述3 SwA配置4 SwB配置5 查看配置6 普通模式链路聚合演示 https blog csdn net qq 45042462 article details 120972306 1 拓扑图 2 任务描述
  • Linux 或 树莓派 4B 使用 apt 或 pip 安装 scipy

    下面的安装过程都是在树莓派4B上安装成功的 xff0c 记录一下 xff0c 仅供参考 python 3 7 使用 apt 安装 注 xff1a 这种好像python版本只能在3 8以下 xff0c 其他版本也可尝试 sudo apt ge
  • 树莓派4B 安装 sklearn

    本文记录在树莓派4B中安装sklearn库的步骤以及安装时遇到的问题 安装步骤 sudo pip3 install numpy 61 61 1 23 5 sudo apt get install python3 numpy python3
  • navicat连接mysql报错1251的解决方法

    navicat连接mysql报错1251的解决方法 1 新安装的mysql8 xff0c 使用破解版的navicat连接的时候一直报错 xff0c 如图所示 xff1a 2 网上查找原因发现是mysql8 之前的版本中加密规则是mysql
  • 一个简单的flask实例

    Flask是python编写的轻量级的web框架 span class token comment 导入Flask类 span span class token keyword from span flask span class toke
  • 基础命令(四)

    LINUX基础命令 xff08 四 xff09 一 Tail命令 1 tail使用方法 tail命令用途是依照要求将指定的文件的最后部分输出到标准设备 xff0c 通常是终端 xff0c 通俗讲来 xff0c 就是把某个档案文件的最后几行显
  • Snipaste常用快捷键(详细总结)

    Snipaste快捷键 xff08 详细总结 xff09 全局快捷键 全局操作截屏F1贴图F3退出当前截图Esc截屏并自动复制Ctrl 43 F1隐藏 显示所有贴图Shift 43 F3切换到另一组贴图Ctrl 43 F3 鼠标贴图相关操作
  • 4位数值比较器电路

    4位数值比较器电路 题目描述 xff1a 使用门级描述方式 xff0c 实现4位数值比较器 某4位数值比较器的功能如下表 96 timescale 1ns 1ns module comparator 4 input 3 0 A input
  • Maven项目pom.xml project标签爆红解决方法

    今天在打开项目的时候 xff0c 发现了一个Maven项目的问题 xff0c 在Maven项目的pom xml文件中 xff0c project标签爆出了一个错误 parent relativePath of POM com hrp spr
  • 人工智能学习笔记五——孪生神经网络

    本文将用孪生神经网络模型 xff0c 对手写数字集minist进行相似度比较 xff0c 用的框架是keras 如果还不清楚神经网络 xff0c 可以看一下这篇文章 神经网络 caodong0225 github io MNIST 是一个手
  • Docker Swarm实战初探

    声明 xff1a 本文CSDN作者原创投稿文章 xff0c 未经许可禁止任何形式的转载 xff0c 原文链接 环境 宿主机 xff1a macOS 10 15 7虚拟机平台 xff1a Parallels Desktop 15 1 2虚拟机
  • 零基础DIY四轴飞行器超级详细保姆级教程(STM32F407ZGT6主控、WIFI图传、陀螺仪平衡、气压计/超声波定高、手机蓝牙控制等功能)

    前言 大四毕业后暑假没事做就花了一点DIY了一个四轴飞行器 xff0c 是比较大的那种F450机架 xff0c 不是那种PCB板做机架的小四轴 xff0c 因为我也是从零基础开始做的四轴 xff0c 现在就想把自己的过程写成博客分享在网上
  • shell教程

    shell 简介 Shell是一种脚本语言 xff0c 通常用于在Unix和类Unix操作系统上进行命令行交互 它是用户与操作系统内核之间的接口 xff0c 允许用户通过命令行或脚本文件来控制计算机上的操作 Shell程序通常用于执行复杂的
  • matlab画图常用函数image、imagesc、imshow区别

    1 image函数 从数组显示图像 xff0c 直接把矩阵中的值当作索引值 xff08 称为直接映射 xff09 xff0c 即数值1对应RGB1 xff0c 数值2对应于RGB2 xff0c 当小于1或大于64时表现为两端的颜色 语法1
  • 树莓派WiFi连接问题及网页打开问题的解决

    树莓派WiFi连接问题及网页打开问题的解决 一 问题描述 前一段时间在网上买了一个树莓派 4b计划做一个人脸识别的智能锁 xff0c 前一段时间整赶上期末考试 xff0c 挤时间做了做人脸识别以及人体红外感知模块 xff0c 大致能简单实现
  • C++11之正则表达式(regex_match、regex_search、regex_replace)

    在C 43 43 11中引入了正则表达式 字符规则 先来了解一下这个字符的含义吧 字符描述 转义字符 匹配字符行尾 匹配前面的子表达式任意多次 43 匹配前面的子表达式一次或多次 xff1f 匹配前面的子表达式零次或一次 m 匹配确定的m次
  • Java中Lambda表达式使用及详解

    Java中Lambda表达式使用及详解 前言 一 Lambda表达式的简介 Lambda表达式 xff08 闭包 xff09 xff1a java8的新特性 xff0c lambda运行将函数作为一个方法的参数 xff0c 也就是函数作为参