java lambda表达式详解

一、Lambda初识

我们知道,在Java中,接口是不能实例化的,但是接口对象可以指向它的实现类对象。如果接口连实现对象都没有呢?那还可以使用匿名类的方式,如下:

public class JavaTest { 
   
    public static void main(String[] args) { 
   
        Fly fly = new Fly() { 
   
            @Override
            public void fly(String name) { 
   
                System.out.println(name + "飞行");
            }
        };
        fly.fly("张三");
    }
}

interface Fly{ 
   
    abstract void fly(String name);
}

复制

但是,使用匿名内部的方式,代码量其实并不是非常简洁,而为了使代码更加的简洁,Java引进了Lambda表达式的写法,通过更简单的语法,去实现这样功能,使用Lambda表达式简化的代码如下:

public class JavaTest { 
   
    public static void main(String[] args) { 
   
        Fly fly = name -> System.out.println(name + "飞行");
        fly.fly("张三");
    }
}

interface Fly{ 
   
    abstract void fly(String name);
}

复制

通过Lambda表达式完成了同样的效果,但是代码量却精简了非常对,这就是Lambda表达式的魅力。

二、 函数式接口

在学习Lambda表达式的语法之前,首先要知道什么是函数式接口, 只有一个待实现方法 的接口,就叫做函数式接口。

//接口中只有一个待实现的方法 fly,所以这是函数式接口
interface Fly{ 
   
     void fly(String name);
}
//接口中有两个待实现的方法 这是不是函数式接口
interface Run{ 
   
    void fastRun();
    void slowRun();
}
//接口中有两个方法,但其中一个是已经定义好的default方法,真正需要子类去实现的方法只有一个 这是函数式接口
interface Jump{ 
   
    void jump();
    default void highJump(){ 
   
        System.out.println("跳的更高");
    }
}

复制

可以在接口上加**@FunctionalInterface注解,去断言这个接口是函数式接口,如果这个接口不是函数式接口,编译就会提示错误。

为什么要知道什么是函数式接口呢?因为Lambda表达式去简化一个接口的匿名类实现方式,它只能对函数式接口起作用**。 这很容易理解,如果一个接口有多个待实现的方法,Lambda表达式就不能分辨出它现在是对接口中哪个方法进行实现。

三、Lambda表达式语法

Lambda表达式在Java语言中引入了一个操作符**“->”**,该操作符被称为Lambda操作符或箭头操作符。它将Lambda分为两个部分:

左侧:指定了Lambda表达式需要的所有参数 右侧:制定了Lambda体,即Lambda表达式要执行的功能。 像这样:

(parameters) -> expression
或
(parameters) ->{ statements; }

复制

Lambda表达式的除了->和Lambda体,其他的比如参数,小括号,中括号都是可以更加参数类型、方法体代码行数进行省略的。 以如下函数式接口的实现为例:

interface MathOperation { 
   
        int operation(int a, int b);
    }

    interface GreetingService { 
   
        void sayMessage(String message);
    }

    private int operate(int a, int b, MathOperation mathOperation){ 
   
        return mathOperation.operation(a, b);
    }
    
    interface NoParam{ 
   
        int returnOne();
    }

复制

以下是lambda表达式的重要特征:

  • 可选类型声明:Lambda表达式可以不用声明实现方法的参数类型,编译器可以统一识别参数值。
        // 类型声明
        MathOperation addition = (int a, int b) -> a + b;
        // 不用类型声明
        MathOperation subtraction = (a, b) -> a - b;

复制

  • 可选的参数圆括号:一个参数无需定义圆括号,但没有参数或者多个参数需要定义圆括号。
      // 不用括号
        GreetingService greetService1 = message ->
                System.out.println("Hello " + message);

        // 用括号
        GreetingService greetService2 = (message) ->
                System.out.println("Hello " + message);

复制

  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
     // 多条语句不可以省略大括号
        MathOperation multiplication = (int a, int b) -> { 
   
            int num = a+1;
            num = a + b;
            return a * b + num;
        };

        // 单条语句可以省略大括号
        MathOperation division = (int a, int b) -> a / b;

复制

  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。
  // 多条语句的Lambda表达式如果有返回值,需要使用return
        MathOperation multiplication = (int a, int b) -> {
            int num = a+1;
            num = a + b;
            return a * b + num;
        };

        // 单条语句可以省略return
        MathOperation division = (int a, int b) -> a / b;

复制

四、Lambda表达式的使用范围

Lambda表达式并不只是单单的用来简化一个匿名类的创建,它还有更多的用法。

1、为变量赋值

上文中,对Lambda表达式的用法都是为变量赋值的写法,这样可以简化匿名内部类赋值的代码段,提高阅读效率。

MathOperation subtraction = (a, b) -> a - b;

复制

2、作为return结果

interface MathOperation { 
   
        int operation(int a, int b);
    }

    MathOperation getOperation(int a, int b){ 
   
        return (a1, b1) -> a+b;
    }

复制

3、作为数组元素

MathOperation math[] = { 
   
                (a,b) -> a+b,
                (a,b) -> a-b,
                (a,b) -> a*b
        };

复制

4、作为普通方法或者构造方法的参数

public static void main(String args[]){ 

Java8Tester java8Tester = new Java8Tester();
java8Tester.operate(1,2,((a, b) -> a*b));
}
private int operate(int a, int b, MathOperation mathOperation){ 

return mathOperation.operation(a, b);
}
interface MathOperation { 

int operation(int a, int b);
}

复制

五、Lambda表达式的作用域范围

Lambda表达式表达体内,可以访问表达体外的变量,但无法对其他变量进行修改操作。

六、Lambda表达式的引用写法

在学习Lambda的时候,还可能会发现一种比较奇怪的写法,例如下面的代码:

// 方法引用写法
GreetingService greetingService = System.out::println;
greetingService.sayMessage("hello world");

复制

这里出现了一个从来没见过的符号 :: ,这种写法就叫做方法的引用。 显然使用方法引用比普通的Lambda表达式又简洁了一些。

如果函数式接口的实现恰好可以通过调用一个方法来实现,那么我们可以使用方法引用。

public class Java8Tester { 

public static void main(String args[]){ 

// 静态方法引用--通过类名调用
GreetingService greetingService = Test::MyNameStatic;
greetingService.sayMessage("hello");
Test t = new Test();
//实例方法引用--通过实例调用
GreetingService greetingService2 = t::myName;
// 构造方法方法引用--无参数
Supplier<Test> supplier = Test::new;
System.out.println(supplier.get());
}
interface GreetingService { 

void sayMessage(String message);
}
}
class Test { 

// 静态方法
public static void MyNameStatic(String name) { 

System.out.println(name);
}
// 实例方法
public void myName(String name) { 

System.out.println(name);
}
// 无参构造方法
public Test() { 

}
}

复制

7、Lambda表达式的优缺点

优点:

  • 更少的代码行-lambda表达式的最大好处之一就是减少了代码量。我们知道,lambda表达式只能与功能接口一起使用。例如,Runnable 是一个接口,因此我们可以轻松地应用lambda表达式。
  • 通过将行为作为方法中的参数传递来支持顺序和并行执行-通过在Java 8中使用Stream API,将函数传递给collection方法。现在,集合的职责是以顺序或并行的方式处理元素。
  • 更高的效率-过使用Stream API和lambda表达式,可以在批量操作集合的情况下获得更高的效率(并行执行)。 此外,lambda表达式有助于实现集合的内部迭代,而不是外部迭代。

缺点

  • 运行效率-若不用并行计算,很多时候计算速度没有比传统的 for 循环快。(并行计算有时需要预热才显示出效率优势)
  • 很难调试-Lambda表达式很难打断点,对调式不友好。
  • 不容易看懂-若其他程序员没有学过 lambda 表达式,代码不容易让其他语言的程序员看懂(我学Lambda表达式的原因是看不懂同事写的Lambda表达式代码)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/19261.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

某程序员哀叹:二本计算机,4年开发,年包才40多万。二本真的不如985/211吗?

前段时间&#xff0c;某职场论坛上有人发了一个帖子&#xff0c;发帖人问&#xff1a;为什么大家工资那么高&#xff0c;三五年都六七十万了&#xff1f;我二本计算机专业&#xff0c;四年前端开发&#xff0c;找个年包40万多点就顶头了。 原贴如下&#xff1a; 有网友表示楼主…

2022年平均工资出炉,IT行业又是第一

根据5月9日国家统计局最新资料显示&#xff0c;2022年&#xff0c;全国城镇非私营单位就业人员年平均工资为114029元&#xff0c;比上年增长6.7%&#xff0c;扣除通胀后实际增长4.6%。其中&#xff0c;行业间的差距相当明显。根据资料显示&#xff0c;2022年无论是在私营单位还…

Android---bitmap优化

目录 Bitmap 占用内存大小计算 Bitmap | Drawable | InputStream | Byte[] 之间进行转换 Bitmap 相关方法 BitmapFactory 工厂类 Bitmap 占用内存大小计算 Bitmap 作为位图&#xff0c;需要读入一张图片中每一个像素点的数据&#xff0c;其主要占用内存的地方也正是这些像…

python进阶--月考二

python进阶--月考二 &#xff08;一&#xff09;装饰器&#xff08;二&#xff09;创建名为express.py文件&#xff0c;编写以下推导式&#xff08;25分&#xff09;&#xff08;三&#xff09;创建名为process_test.py的文件&#xff0c;计算1-3000之间的水仙花数&#xff08;…

QT MD4 MD5 Sha1等几种加密方式

QT MD4 MD5 Sha1等几种加密方式 [1] QT MD4 MD5 Sha1等几种加密方式[2] qt MD5 和AES 加密一 、MD5 加密二、AES 加密和解密 [3] QT中sqlite数据库数据加密/混淆---MD5/SHA1/SHA2/SHA3&#xff08;1&#xff09;创建一个加密对象&#xff08;2&#xff09;放入要加密的数据&…

目前可用的ChatGPT网站

本文意在整理可用gpt-3.5、gpt-4.0等网站。 本文主要是方便自己翻阅&#xff0c;如对您也有所帮助&#xff0c;不胜荣幸~ 文章目录 chatgpt.qdymys.cngpttalkchatgpt-cn.cobing.comchat机器人wuguokai.cn总结 chatgpt.qdymys.cn 网址&#xff1a;https://chatgpt.qdymys.cn/限…

SpringCloud —— eureka

目录 1.认识微服务 1.0.学习目标 1.1.单体架构 1.2.分布式架构 1.3.微服务 1.4.SpringCloud 1.5.总结 2.服务拆分和远程调用 2.1.服务拆分原则 2.2.服务拆分示例 2.2.1.导入Sql语句 2.2.2.导入demo工程 2.3.实现远程调用案例 2.3.1.案例需求&#xff1a; 2.3.2.注…

mysql进阶-查询优化-慢查询日志

文章目录 一、什么是慢查询日志二、慢查询日志能干什么2.1 性能分析和优化2.2 诊断和排查问题2.3 数据分析和探索 三、慢查询日志实战3.1 永久开启开启慢查询日志3.2 临时开启慢查询日志3.4 常用命令 四、如何分析慢查询日志五、优化慢查询语句五、总结 一、什么是慢查询日志 …

观察者设计模式(Observer Design Pattern)[论点:概念、组成角色、相关图示、示例代码、框架中的运用、适用场景]

文章目录 概念组成角色相关图示示例代码框架中的运用适用场景 概念 观察者设计模式&#xff08;Observer Design Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一种对象间的一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象&#xff0c;当…

SpringBoot 配置文件

前言&#xff1a; 本篇主要介绍两种配置文件格式&#xff0c;分别为properties与yml(yaml)。 需要注意的是&#xff1a; 两个配置文件从功能上来讲是可以同时存在的&#xff0c;但是企业中通常会规定使用某一种格式的配置文件。如果同一个配置出现在两种格式的配置文件中的话&a…

微波方向有哪些SCI期刊推荐? - 易智编译EaseEditing

微波方向的SCI期刊推荐包括&#xff1a; IEEE Transactions on Microwave Theory and Technology&#xff1a; 该期刊是电磁场与微波技术领域的著名期刊&#xff0c;被世界上许多研究机构和大学广泛引用。 IEEE Transactions on Antennas and Propagation&#xff1a; 该期刊…

English Learning - L3 作业打卡 Lesson1 Day5 2023.5.9 周二

English Learning - L3 作业打卡 Lesson1 Day5 2023.5.9 周二 引言&#x1f349;句1: Fast loud music is popular with many people .成分划分爆破语调 &#x1f349;句2: They may say the music is red hot, especially the kind called Dixieland jazz.成分划分爆破语调 &a…

AI孙燕姿项目实现

最近在b站刷到很多关于ai孙笑川唱的歌曲&#xff0c;加上最近大火的ai孙燕姿&#xff0c; 这下“冷门歌手”整成热门歌手了 于是写下一篇文章&#xff0c; 如何实现属于的ai歌手。 注意滥用ai&#xff0c;侵犯他人的名誉是要承担法律责任的 下面是一些所需的文件链接&#xff…

低代码信创开发核心技术(一):基于Vue.js的描述依赖渲染DDR实现模型驱动的组件

前言 随着数字化转型的不断发展&#xff0c;低代码开发平台已成为企业快速建立自己的应用程序的首选方案。然而&#xff0c;实现这样一个平台需要具备高效、灵活和可定制化的能力。这正是基于描述依赖渲染&#xff08;Description dependency rendering&#xff09;所实现的。…

C语言CRC-16 XMODEM格式校验函数

C语言CRC-16 XMODEM格式校验函数 CRC-16校验产生2个字节长度的数据校验码&#xff0c;通过计算得到的校验码和获得的校验码比较&#xff0c;用于验证获得的数据的正确性。基本的CRC-16校验算法实现&#xff0c;参考&#xff1a; C语言标准CRC-16校验函数。 不同应用规范通过对…

三分钟阿里云服务器u1通用算力型性能、使用限制及费用说明

阿里云服务器u1是通用算力型云服务器&#xff0c;CPU采用2.5 GHz主频的Intel(R) Xeon(R) Platinum处理器&#xff0c;通用算力型u1云服务器不适用于游戏和高频交易等需要极致性能的应用场景及对业务性能一致性有强诉求的应用场景(比如业务HA场景主备机需要性能一致)&#xff0c…

C/C++每日一练(20230512) 成绩打印、补齐数组、水仙花数

目录 1. 成绩打印 ※ 2. 按要求补齐数组 &#x1f31f;&#x1f31f;&#x1f31f; 3. 水仙花数 ※ &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 成绩打印 一个班有10个同学&am…

隐语v0.8.2版本更新,首次发布TEEU

隐语v0.8.2版本更新&#x1f31f; 应用层 机器学习&#xff1a; - MPC 纵向 LR &#xff08;SSRegression&#xff09;新增 Policy SGD 优化器和 Early Stopping 支持&#xff0c;减少调参成本&#xff0c;加快收敛速度&#xff1b; - WOE 分箱进行了若干优化&#xff0c;性…

本地搭建wamp服务器并内网穿透实现无公网IP远程访问

文章目录 前言1.Wamp服务器搭建1.1 Wamp下载和安装1.2 Wamp网页测试 2. Cpolar内网穿透的安装和注册2.1 本地网页发布2.2 Cpolar云端设置2.3 Cpolar本地设置 3. 公网访问测试4. 结语 转载自cpolar极点云的文章&#xff1a;无公网IP&#xff1f;教你在外远程访问本地Wamp服务器「…

前端CSS学习(三)

1、盒子模型 盒子的概念1、页面中的每一个标签&#xff0c;都可看做是一 个“盒子” &#xff0c;通过盒子的视角更方便的进行布局2、浏览器在渲染 (显示)网页时&#xff0c;会将网页中的元素看做是一个个的矩形区域&#xff0c;我们也形象的称之为盒子CSS中规定每个盒子分别由…