Java8新特性 - Lambda表达式

目录

一、Lambda表达式

1.1、为什么使用Lambda表达式?

1.2、Lambda的标准格式

Lambda的标准格式

无参无返回值的Lambda

有参有返回值的Lambda

1.3、Lambda的实现原理

1.4、Lambda省略模式

1.5、Lambda表达式的前提条件

1.6、Lambda与匿名内部类对比

1.7、JDK8接口新增的两个方法

JDK8接口增强介绍

接口默认方法的定义格式

接口默认方法的使用

接口静态方法的定义格式

接口静态方法的使用

接口静态方法与默认方法的区别

1.8、常用内置函数式接口

Supplier

Consumer

Function

Predicate

1.8、方法引用

Lambda的冗余场景

常见引用方式

对象名::引用成员方法

类名::引用静态方法

类名::引用实例方法

类名::new引用构造器

数组::new引用数组构造器


一、Lambda表达式

1.1、为什么使用Lambda表达式?

Lambda是一个匿名函数,我们可以把Lambda表达式理解为一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

匿名内部类与Lambda表达式写法对比:显而易见Lambda表达式更加简便。

public class TestLambda {public static void main(String[] args) {//使用匿名内部类new Thread(new Runnable() {@Overridepublic void run() {System.out.println("普通匿名内部类执行了");}}).start();//使用Lambdanew Thread(()->{System.out.println("Lambda表达式执行了");}).start();}
}

1.2、Lambda的标准格式

Lambda的标准格式

(参数类型 参数名称) -> {代码体;
}

无参无返回值的Lambda

public interface Swimmable {public abstract void swimming();
}
public class TestLambda2 {public static void main(String[] args) {//无参无返回值的LambdagoSwimming(()->{System.out.println("无参无返回值的Lambda");});}public static void goSwimming(Swimmable s){s.swimming();}
}

有参有返回值的Lambda

public interface Swimmable {public abstract int swimming(String name);
}
public class TestLambda2 {public static void main(String[] args) {//有参有返回值的LambdagoSwimming((String name)->{System.out.println(name + "正在游泳");return 10;});}public static void goSwimming(Swimmable s){s.swimming("尼采");}
}

1.3、Lambda的实现原理

普通的匿名内部类编译后是会生成一个名字带$的类,但Lambda不会生成其它类文件,但是Lambda表达式会在这个类中新生成一个私有的静态方法,并且Lambda表达式的代码会放到这个新增的方法中。同时Lambda底层还是会以普通匿名内部类的形式去展现,只不过在内部类中调用了之前生成的私有的静态方法。

1.4、Lambda省略模式

在Lambda标准格式的基础上,使用省略写法的规则为:

1、小括号内参数的类型可以省略。

2、如果小括号内有且仅有一个参数,则小括号可以省略。

3、如果大括号内有且仅有一个语句,可以同时省略大括号、return关键字及语句分号。

public static void main(String[] args) {List<String> books = new ArrayList<>();books.add("百年孤独");books.add("霍乱时期的爱情");books.add("一桩事先张扬的凶杀案");books.add("没有人给他写信的上校");//省略前books.forEach((t) -> {System.out.println(t);});//省略后books.forEach(t -> System.out.println(t));
}

        

1.5、Lambda表达式的前提条件

1、方法的参数或局部变量类型必须为接口才能使用Lambda。

2、接口中有且仅有一个抽象方法(函数式接口)。

1.6、Lambda与匿名内部类对比

1、所需的类型不一样:

匿名内部类:需要的类型可以是类、抽象类、接口。

Lambda:需要的类型必须是接口。

2、抽象方法的数量不一样:

匿名内部类:所需的接口中抽象方法的数量随意。

Lambda:表达式所需的接口只能有一个抽象方法。

3、实现原理不同:

匿名内部类:在编译后会形成class。

Lambda:在程序运行的时候动态生成class。

1.7、JDK8接口新增的两个方法

JDK8接口增强介绍

JDK8以前的接口:

interface 接口名 {静态常量;抽象方法;
}

JDK8的接口:

interface 接口名 {静态常量;抽象方法;默认方法;静态方法;
}

接口中的默认方法实现类不需要重写,可以直接使用,实现类也可以根据需要重写。这样就方便接口的扩展。

接口默认方法的定义格式

interface 接口名 {public default void method(){//代码}
}

接口默认方法的使用

public interface Swimmable {public default void eat(String name){System.out.println(name + "在吃饭");}
}class SwimmableImpl implements Swimmable{}
public class TestLambda2 {public static void main(String[] args) {Swimmable sw = new SwimmableImpl();sw.eat("马尔克斯");}
}

接口静态方法的定义格式

interface 接口名 {修饰符 static 返回值类型 方法名(){//代码   }
}

接口静态方法的使用

public interface Swimmable {public static void eat(String name){System.out.println(name + "在吃饭");}
}class SwimmableImpl implements Swimmable{}
public class TestLambda2 {public static void main(String[] args) {Swimmable.eat("马尔克斯"); //接口的静态方法只能用接口名调用}
}

接口静态方法与默认方法的区别

1、默认方法通过实例调用,静态方法通过接口名调用。

2、默认方法可以被继承,实现类可以直接使用接口默认方法,也可以重写接口默认方法。

3、静态方法不能被继承,实现类不能重写接口的静态方法,只能使用接口名调用。

1.8、常用内置函数式接口

他们主要在java.util.function包中。下面是最常用的几个接口:

Supplier

供给型接口,对应的Lambda表达式需要“对外提供”一个符合泛型类型的数据对象。

@FuncationalInterface
public interface Supplier<T> {public abstract T get();  
}

实例:返回数组元素最大值

public class TestLambda2 {public static void main(String[] args) {int[] arr = {5,8,1,20,2,17};printMax(() -> {Arrays.sort(arr);return arr[arr.length - 1];});}public static void printMax(Supplier<Integer> supplier){int max = supplier.get();System.out.println(max);}
}

Consumer

与Supplier接口正好相反,它不是生产一个数据,而是消费一个数据。

@FuncationalInterface
public interface Consumer<T> {public abstract void accept(T t);  
}

实例:将一个字符串转成大写和小写的字符串

public class TestLambda2 {public static void main(String[] args) {printHello((String str) -> {System.out.println(str.toUpperCase());});}public static void printHello(Consumer<String> consumer){consumer.accept("hello");}
}

Function

java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。有参数有返回值。

@FuncationalInterface
public interface Function<T,R> {public abstract R apply(T t);  
}

实例:将字符串转成数字

public class TestLambda2 {public static void main(String[] args) {getNumber((String str) -> {Integer i = Integer.parseInt(str);return i;});}public static void getNumber(Function<String,Integer> function){Integer num = function.apply("10");System.out.println(num);}
}

Predicate

有时候我们需要对某种类型进行判断,从而得到一个boolean值结果。

@FuncationalInterface
public interface Predicate<T> {public abstract boolean test(T t);  
}

实例1:判断一个人名如果超过3个字就认为是很长的名字

public class TestLambda2 {public static void main(String[] args) {isLongName((String name) -> {return name.length() > 3;});}public static void isLongName(Predicate<String> predicate){boolean b = predicate.test("马尔克斯");System.out.println(b);}
}

实例2:判断一个字符串中包含W,也包含H

public class TestLambda2 {public static void main(String[] args) {exercise((String str) -> {return str.contains("H");},(String str) -> {return str.contains("W");});}public static void exercise(Predicate<String> p1,Predicate<String> p2){boolean b1 = p1.test("Hello");boolean b2 = p2.test("World");if(b1 && b2){System.out.println("既包含W,也包含H");}}
}

使用and可以将代码改写为:

public class TestLambda2 {public static void main(String[] args) {exercise((String str) -> {return str.contains("H");},(String str) -> {return str.contains("W");});}public static void exercise(Predicate<String> p1,Predicate<String> p2){String str = "HelloWorld";boolean b = p1.and(p2).test(str);if(b)System.out.println("既包含W,也包含H");}
}

1.8、方法引用

Lambda的冗余场景

public class Y {public static void main(String[] args) {//使用方法引用//这个指定的方法getMax去重写接口的抽象方法accept,到时候调用接口的抽象方法就是调用传递过去的方法printMax(Y::getMax);}public static void getMax(int[] arr){int sum = 0;for (int n : arr){sum += n;}System.out.println(sum);}public static void printMax(Consumer<int[]> consumer){int[] arr = {11,22,33,44,55};consumer.accept(arr);}
}

常见引用方式

1、对象::方法名

2、类名::静态方法

3、类名::普通方法

4、类名::构造器

5、String[]::数组构造器

对象名::引用成员方法

//正常使用Lambda
@Test
public void test01(){Date now = new Date();Supplier<Long> su1 = () -> {return now.getTime();};Long aLong = su1.get();System.out.println(aLong);
}
//对象引用Lambda
@Test
public void test02(){Date now = new Date();Supplier<Long> su2 = now::getTime;Long aLong = su2.get();System.out.println(aLong);
}

注意:你调用方法的参数和返回值要和接口中抽象方法的返回值和参数要一致比如上述代码,getTime()方法参数是无参,返回值是Long类型,那我们接口中的get()方法也是一样的。


类名::引用静态方法

@Test
public void test01(){Supplier<Long> sup = System::currentTimeMillis;Long aLong = sup.get();System.out.println(aLong);
}

类名::引用实例方法

Java面向对象中,类名只能调用静态方法,类名引用实例方法是有前提的,实际上是拿第一个参数作为方法的调用者。

当调用的方法无参时:

@Test
public void test01(){Function<String,Integer> fun = String::length;Integer length = fun.apply("Hello");System.out.println(length);
}

当方法有一个参数时:

@Test
public void test02(){BiFunction<String,Integer,String> fun = String::substring;String result = fun.apply("HelloWorld", 3);System.out.println(result);
}

类名::new引用构造器

由于构造器的名称与类名完全一样,所以构造器引用使用类名称::new的格式表示。

@Test
public void test01(){Supplier<Person> sup = Person::new;Person person = sup.get();System.out.println(person);
}

数组::new引用数组构造器

数组也是Object的子类对象,所以同样具有构造器,只是语法稍有不同。

@Test
public void test01(){Function<Integer,int[]> fun = int[]::new;int[] apply = fun.apply(5);System.out.println(apply);
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringMvc框架入门使用(详细教程)

目录 ​编辑 1.SpringMVC框架是什么&#xff1f; 2.SpringMVC工作流程 3.SpringMVC的入门 3.1 pom.xml 3.2spring-mvc.xml 3.3web.xml 3.4 建立一个web的方法 4.5 建立一个首页 4.6效果展示 4.图片处理 1.SpringMVC框架是什么&#xff1f; Spring MVC是一个基…

嵌入式Linux开发实操(十六):Linux驱动模型driver model

嵌入式linux下驱动模型: 1、驱动的绑定 驱动程序绑定driver binding 驱动程序绑定是将设备device与可以控制它的设备驱动程序driver相关联的过程。总线驱动程序bus driver通常会处理,因为有特定于总线bus的结构来表示设备device和驱动程序driver。使用通用的设备device和设…

基于 Flink CDC 构建 MySQL 和 Postgres 的 Streaming ETL

官方网址&#xff1a;https://ververica.github.io/flink-cdc-connectors/release-2.3/content/%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B/mysql-postgres-tutorial-zh.html官方教程有些坑&#xff0c;经过自己实测&#xff0c;记录个笔记。 服务器环境&#xff1a; VM虚拟机&am…

潜艇来袭(Qt官方案例-2维动画游戏)

一、游戏介绍 1 开始界面 启动程序&#xff0c;进入开始界面。 2 开始新游戏 点击菜单&#xff1a;File》New Game &#xff08;或者CtrlN&#xff09;进入新游戏。 开始新游戏之后&#xff0c;会有一个海底的潜艇&#xff0c;和水面舰艇对战。 计算机&#xff1a;自动控制…

STM32f103入门(4)对射式红外传感器计次(外部中断)

中断:在主程序运行过程中&#xff0c;出现了特定的中断触发条件 (中断源)&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序处理完成后又返回原来被暂停的位置继续运行中断优先级:当有多个中断源同时申请中断时&#xff0c;CPU会根据中断源的轻重缓急进…

深度学习推荐系统(四)WideDeep模型及其在Criteo数据集上的应用

深度学习推荐系统(四)Wide&Deep模型及其在Criteo数据集上的应用 在2016年&#xff0c; 随着微软的Deep Crossing&#xff0c; 谷歌的Wide&Deep以及FNN、PNN等一大批优秀的深度学习模型被提出&#xff0c; 推荐系统全面进入了深度学习时代&#xff0c; 时至今日&#x…

聚焦磷酸铁锂产线革新,宏工科技一站式解决方案

兼顾了低成本与安全性两大属性&#xff0c;磷酸铁锂市场在全球范围内持续升温&#xff0c;并有望保持较高的景气度。巨大的需求空间之下&#xff0c;行业对于锂电装备企业的自动化与智能化水平、整线交付能力、产品效率与稳定性等均提出了新的要求。 以宏工科技股份有限公司&a…

C#通过ModbusTcp协议读写西门子PLC中的浮点数

一、Modbus TCP通信概述 MODBUS/TCP是简单的、中立厂商的用于管理和控制自动化设备的MODBUS系列通讯协议的派生产品&#xff0c;显而易见&#xff0c;它覆盖了使用TCP/IP协议的“Intranet”和“Internet”环境中MODBUS报文的用途。协议的最通用用途是为诸如PLC&#xff0c;I/…

LiveGBS流媒体平台GB/T28181功能-支持数据库切换为高斯数据库信创瀚高数据信创数据库

LiveGBS流媒体平台GB/T28181功能-支持数据库切换为高斯数据库信创瀚高数据信创数据库 1、如何配置切换高斯数据库&#xff1f;2、如何配置切换信创瀚高数据库&#xff1f;3、搭建GB28181视频直播平台 1、如何配置切换高斯数据库&#xff1f; livecms.ini -> [db]下面添加配…

华为Mate60低调发布,你所不知道的高调真相?

华为Mate60 pro 这两天的劲爆新闻想必各位早已知晓&#xff0c;那就是华为Mate60真的来了&#xff01;&#xff01;&#xff01;并且此款手机搭载了最新国产麒麟9000s芯片&#xff0c;该芯片重新定义了手机性能的巅峰。不仅在Geekbench测试中表现出色&#xff0c;还在实际应用…

成都瀚网科技有限公司:抖店的评论会消失吗?

抖店是抖音推出的电子商务平台。很多用户在购物后都会对产品进行评价。但有时用户可能会发现抖店评论缺失&#xff0c;让用户产生一些疑惑和困惑。本文将围绕这个问题提供一些答案和解决方案。 1.为什么抖店评论不见了&#xff1f; 首先需要明确的是&#xff0c;抖店评论消失可…

单值二叉树

目录 题目题目要求示例 解答方法一、实现思路时间复杂度和空间复杂度代码 方法二、实现思路时间复杂度和空间复杂度代码 题目 单值二叉树 题目要求 题目链接 示例 解答 方法一、 递归 实现思路 时间复杂度和空间复杂度 时间复杂度&#xff1a;O(N) 空间复杂度&#xf…

Jenkins详解(三)

Jenkins详解(三) 目录 Jenkins详解(三) 1、Jenkins介绍2、Jenkins CI/CD 流程3、部署环境 3.1 环境准备3.2 安装GitLab3.3 初始化GitLab3.4 GitLab中文社区版补丁包安装3.5 修改GitLab配置文件/etc/gitlab/gitlab.rb3.6 在宿主机输入 http://192.168.200.26:88 地址就可以访问了…

什么是AJAX?如何使用原生JavaScript搭建AJAX请求?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;⭐ 原生JavaScript中的AJAX请求1. 创建XMLHttpRequest对象2. 配置请求3. 设置回调函数4. 发送请求 ⭐ 完整示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开…

实现Android APK瘦身99.99%

摘要&#xff1a; 如何瘦身是 APK 的重要优化技术。APK 在安装和更新时都需要经过网络下载到设备&#xff0c;APK 越小&#xff0c;用户体验越好。本文作者通过对 APK 内在机制的详细解析&#xff0c;给出了对 APK 各组成成分的优化方法及技术&#xff0c;并实现了一个基本 APK…

Unity 安卓(Android)端AVProVideo插件播放不了视频,屏幕一闪一闪的

编辑器运行没有问题&#xff0c;但是安卓就有问题&#xff0c;在平板上运行就会报错&#xff1a; vulkan graphics API is notsupported 说不支持Vulkan图形API,解决方法&#xff1a;把Vulkan删除掉

QTableView合并单元格

QtableView的功能 QTableView是Qt框架提供的用于显示表格数据的类。它是基于MVC&#xff08;模型-视图-控制器&#xff09;设计模式的一部分&#xff0c;用于将数据模型和界面视图分离。 以下是一些QTableView的主要特点和功能&#xff1a; 1. 显示表格数据&#xff1a; QTa…

手写Mybatis:第20章-Mybatis 框架源码10种设计模式分析

文章目录 一、类型&#xff1a;创建型模式1.1 工厂模式1.2 单例模式1.3 建造者模式 二、类型&#xff1a;结构型模式2.1 适配器模式2.2 代理模式2.3 组合模式2.4 装饰器模式 三、类型&#xff1a;行为型模式3.1 模板模式3.2 策略模式3.3 迭代器模式 一、类型&#xff1a;创建型…

题①拷贝构造相关笔试题

问&#xff1a;此代码中有几次构造&#xff0c;几次拷贝构造&#xff1f; W f&#xff08;W u&#xff09; {W v(u);W w v;return w; } int main() {w x;w y f(x);return 0;解析&#xff1a;一次构造&#xff0c;四次拷贝构造。 再来一题 W f&#xff08;W u&#xff09;…

Redis未授权访问漏洞复现

Redis 简单使用 Redis 未设置密码&#xff0c;客户端工具可以直接链接。 Redis 是非关系型数据库系统&#xff0c;没有库表列的逻辑结构&#xff0c;仅仅以键值对的方式存储数据。 先启动容器 Redis 未设置密码&#xff0c;客户端工具可以直接链接 https://github.com/xk11z/…