​Lambda表达式详解​-初遇者-很细

news/2023/12/9 9:24:36

目录

Lambda简介

对接口的要求

Lambda 基础语法

Lambda 语法简化

Lambda 表达式常用示例

lambda 表达式引用方法

构造方法的引用

lambda 表达式创建线程

遍历集合

删除集合中的某个元素

集合内元素的排序

Lambda 表达式中的闭包问题


Lambda简介

Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

JDK 也提供了大量的内置函数式接口供我们使用,使得 Lambda 表达式的运用更加方便、高效。

对接口的要求

虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法

jdk 8 中有另一个新特性:default, 被 default 修饰的方法会有默认实现,不是必须被实现的方法,所以不影响 Lambda 表达式的使用。

@FunctionalInterface

修饰函数式接口的,要求接口中的抽象方法只有一个。 这个注解往往会和 lambda 表达式一起出现。

Lambda 基础语法

我们这里给出六个接口,后文的全部操作都利用这六个接口来进行阐述。

/**多参数无返回*/@FunctionalInterface
public interface NoReturnMultiParam {void method(int a, int b);
}/**无参无返回值*/@FunctionalInterface
public interface NoReturnNoParam {void method();
}/**一个参数无返回*/@FunctionalInterface
public interface NoReturnOneParam {void method(int a);
}/**多个参数有返回值*/@FunctionalInterface
public interface ReturnMultiParam {int method(int a, int b);
}/*** 无参有返回*/
@FunctionalInterface
public interface ReturnNoParam {int method();
}/**一个参数有返回值*/
@FunctionalInterface
public interface ReturnOneParam {int method(int a);
}

语法形式为 () -> {},其中 () 用来描述参数列表,{} 用来描述方法体,-> 为 lambda运算符 ,读作(goes to)。

import lambda.interfaces.*;
public class Test1 {public static void main(String[] args) {//无参无返回 定义NoReturnNoParam noReturnNoParam = () -> {System.out.println("NoReturnNoParam");};//调用noReturnNoParam.method();//一个参数无返回NoReturnOneParam noReturnOneParam = (int a) -> {System.out.println("NoReturnOneParam param:" + a);};noReturnOneParam.method(6);//多个参数无返回NoReturnMultiParam noReturnMultiParam = (int a, int b) -> {System.out.println("NoReturnMultiParam param:" + "{" + a +"," + + b +"}");};noReturnMultiParam.method(6, 8);//无参有返回值ReturnNoParam returnNoParam = () -> {System.out.print("ReturnNoParam");return 1;};int res = returnNoParam.method();System.out.println("return:" + res);//一个参数有返回值ReturnOneParam returnOneParam = (int a) -> {System.out.println("ReturnOneParam param:" + a);return 1;};int res2 = returnOneParam.method(6);System.out.println("return:" + res2);//多个参数有返回值ReturnMultiParam returnMultiParam = (int a, int b) -> {System.out.println("ReturnMultiParam param:" + "{" + a + "," + b +"}");return 1;};int res3 = returnMultiParam.method(6, 8);System.out.println("return:" + res3);}}

Lambda 语法简化

我们可以通过观察以下代码来完成代码的进一步简化,写出更加优雅的代码。

import lambda.interfaces.*;
public class Test2 {public static void main(String[] args) {//1.简化参数类型,可以不写参数类型,但是必须所有参数都不写NoReturnMultiParam lamdba1 = (a, b) -> {System.out.println("简化参数类型");};lamdba1.method(1, 2);//2.简化参数小括号,如果只有一个参数则可以省略参数小括号NoReturnOneParam lambda2 = a -> {System.out.println("简化参数小括号");};lambda2.method(1);//3.简化方法体大括号,如果方法条只有一条语句,则可以省略方法体大括号NoReturnNoParam lambda3 = () -> System.out.println("简化方法体大括号");lambda3.method();//4.如果方法体只有一条语句,并且是 return 语句,则可以省略方法体大括号ReturnOneParam lambda4 = a -> a+3;System.out.println(lambda4.method(5));ReturnMultiParam lambda5 = (a, b) -> a+b;System.out.println(lambda5.method(1, 1));}}


 

Lambda 表达式常用示例

lambda 表达式引用方法

有时候我们不是必须要自己重写某个匿名内部类的方法,我们可以可以利用 lambda表达式的接口快速指向一个已经被实现的方法。

语法

方法归属者::方法名 静态方法的归属者为类名,普通方法归属者为对象

public class Exe1 {public static void main(String[] args) {ReturnOneParam lambda1 = a -> doubleNum(a);System.out.println(lambda1.method(3));//lambda2 引用了已经实现的 doubleNum 方法ReturnOneParam lambda2 = Exe1::doubleNum;System.out.println(lambda2.method(3));Exe1 exe = new Exe1();//lambda4 引用了已经实现的 addTwo 方法ReturnOneParam lambda4 = exe::addTwo;System.out.println(lambda4.method(2));}/*** 要求* 1.参数数量和类型要与接口中定义的一致* 2.返回值类型要与接口中定义的一致*/public static int doubleNum(int a) {return a * 2;}public int addTwo(int a) {return a + 2;}}

构造方法的引用

一般我们需要声明接口,该接口作为对象的生成器,通过 类名::new 的方式来实例化对象,然后调用方法返回对象。

interface ItemCreatorBlankConstruct {Item getItem();
}interface ItemCreatorParamContruct {Item getItem(int id, String name, double price);
}public class Exe2 {public static void main(String[] args) {ItemCreatorBlankConstruct creator = () -> new Item();Item item = creator.getItem();ItemCreatorBlankConstruct creator2 = Item::new;Item item2 = creator2.getItem();ItemCreatorParamContruct creator3 = Item::new;Item item3 = creator3.getItem(112, "鼠标", 135.99);}}

lambda 表达式创建线程

我们以往都是通过创建 Thread 对象,然后通过匿名内部类重写 run() 方法,一提到匿名内部类我们就应该想到可以使用 lambda 表达式来简化线程的创建过程。

    Thread thread=new Thread( new Runnable() {@Overridepublic void run() {}});//简化后Thread t = new Thread(() -> {for (int i = 0; i < 10; i++) {System.out.println(2 + ":" + i);}});t.start();

遍历集合

我们可以调用集合的 public void forEach(Consumer<? super E> action) 方法,通过 lambda 表达式的方式遍历集合中的元素。以下是 Consumer 接口的方法以及遍历集合的操作。Consumer 接口是 jdk 为我们提供的一个函数式接口。

    @FunctionalInterfacepublic interface Consumer<T> {void accept(T t);//....}ArrayList<Integer> list = new ArrayList<>();Collections.addAll(list, 1,2,3,4,5);//lambda表达式 方法引用list.forEach(System.out::println);list.forEach(element -> {if (element % 2 == 0) {System.out.println(element);}});

删除集合中的某个元素

我们通过public boolean removeIf(Predicate<? super E> filter)方法来删除集合中的某个元素,Predicate 也是 jdk 为我们提供的一个函数式接口,可以简化程序的编写。

      ArrayList<Item> items = new ArrayList<>();items.add(new Item(11, "小牙刷", 12.05 ));items.add(new Item(5, "日本马桶盖", 999.05 ));items.add(new Item(7, "格力空调", 888.88 ));items.add(new Item(17, "肥皂", 2.00 ));items.add(new Item(9, "冰箱", 4200.00 ));items.removeIf(ele -> ele.getId() == 7);//通过 foreach 遍历,查看是否已经删除items.forEach(System.out::println);

集合内元素的排序

在以前我们若要为集合内的元素排序,就必须调用 sort 方法,传入比较器匿名内部类重写 compare 方法,我们现在可以使用 lambda 表达式来简化代码。

        ArrayList<Item> list = new ArrayList<>();list.add(new Item(13, "背心", 7.80));list.add(new Item(11, "半袖", 37.80));list.add(new Item(14, "风衣", 139.80));list.add(new Item(12, "秋裤", 55.33));//通常写法/*list.sort(new Comparator<Item>() {@Overridepublic int compare(Item o1, Item o2) {return o1.getId()  - o2.getId();}});*///简化写法list.sort((o1, o2) -> o1.getId() - o2.getId());System.out.println(list);

Lambda 表达式中的闭包问题

这个问题我们在匿名内部类中也会存在,如果我们把下例注释放开会报错,告诉我 num 值是 final 不能被改变。这里我们虽然没有标识 num 类型为 final,但是在编译期间虚拟机会帮我们加上 final 修饰关键字。

import java.util.function.Consumer;
public class Main {public static void main(String[] args) {int num = 10;Consumer<String> consumer = ele -> {System.out.println(num);};//num = num + 2;consumer.accept("hello");}
}


http://www.ppmy.cn/news/89631.html

相关文章

详解Java项目安全方向解决方案

Java作为一种广泛使用的编程语言&#xff0c;广泛应用于各种企业级应用程序的开发中。但是&#xff0c;Java应用程序被黑客攻击是一种常见现象&#xff0c;因此保障Java应用程序的安全至关重要。 在Java项目开发中&#xff0c;安全方向主要包括以下几个方面&#xff1a;认证、…

C#使用HTTP发送POST Params传参值为Json字符串解决

Post&#xff1a;方法 public static string Post(string url, Dictionary<string, string> dic) { string tempMessage ""; System.Net.WebClient WebClientObj new System.Net.WebClient(); System.Collectio…

VR全景智慧城市:构筑未来城市的数字化大融合

引言&#xff1a; 现代城市正处于数字化时代的浪潮之中&#xff0c;而在这个数字化浪潮中&#xff0c;VR全景智慧城市正以令人瞩目的方式崭露头角。随着虚拟现实&#xff08;VR&#xff09;技术的不断进步和智慧城市的发展需求&#xff0c;VR全景智慧城市作为数字技术与城市发展…

【TI毫米波雷达笔记】IWR6843AOPEVM-G+DCA1000EVM的mmWave Studio数据读取、配置及避坑

【TI毫米波雷达笔记】IWR6843AOPEVM-GDCA1000EVM的mmWave Studio数据读取、配置及避坑 硬件方面连接好以后 就可以打开mmWave Studio了 配置 如果硬件配置成功 则可以通过mmWave Studio的Output看到配置信息 按照如图步骤 在radar api里面一步步来操作 其中 RS232选择波特率…

国家信息安全测评信息安全服务资质证书(安全工程类一级)申请条件

中国信息安全测评中心&#xff08;以下简称CNITSEC&#xff09;是经中央批准成立的国家信息安全权威测评机构&#xff0c;职能是开展信息安全漏洞分析和风险评估工作&#xff0c;对信息技术产品、信息系统和工程的安全性进行测试与评估。对信息安全服务和人员的资质进行审核与评…

内网渗透(八十)之搭建额外域控

搭建额外域控 我们在之前搭建完成Windows Server 2012 R2 域控的基础上搭建一个额外的域控。多个域控的好处在于,当其中有域控出现了故障,仍然能够由其他域控来提供服务。选择一台Windows Server 2012 R2 服务器作为额外域控,主机名为DC2. 首先在DC2上配置IP地址为192.168…

【Lychee图床】本地电脑搭建私人图床,公网远程访问

文章目录 1.前言2. Lychee网站搭建2.1. Lychee下载和安装2.2 Lychee网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 转发自CSDN风浪越大%鱼越贵的文章&#xff1a;Lychee图床 - 本地配置属于自己的相册管理系统并远…

Spring源码阅读:Spring事务传播特性

一、概述 我们平常工作中经常会听到事务的传播级别&#xff0c;但是使用中基本不会太调整这个事务传播级别&#xff0c;因为没什么业务场景需要我们这么做&#xff0c;只需要使用原有的事务传播级别即可解决95%的业务场景。但是为了那5%的业务场景&#xff0c;我们还是还要学习…

开发小程序流程

小程序的诞生&#xff0c;是继微信公众号之后的又一款火爆的 APP&#xff0c;并且小程序的市场需求也是非常大的。在小程序出现后&#xff0c;很多商家都想开发自己的小程序&#xff0c;但是因为不知道怎么开发&#xff0c;所以对此感到迷茫。下面就由爱尚网络科技来为大家介绍…

java urlencode() javaurlencode转utf

Java中URL传中文时乱码的问题相信不少朋友都遇到过&#xff0c;最近就遇到一个问题&#xff0c;就是在Action当中把一条中文信息绑定在URL的后面&#xff0c;ActionForward到别一个页面时&#xff0c;用reqeust.getParameter取出是出现乱码的问题。 解决办法&#xff1a; 1、…

淘宝层级改版,五力模型上线!

最近临近618&#xff0c;淘系又各种功能改版&#xff0c;现在店铺层级也开始陆续改版了。从原来的只需要提升销售金额&#xff0c;到现在的五力模型。我们先说一下原来的店铺层级考核&#xff0c;跟现在的区别主要是哪&#xff1f; 1.原来店铺层级的考核升级特别简单&#xff0…

微信删除的好友如何找回来

微信是一个广泛使用的社交媒体平台&#xff0c;它允许用户发送消息、共享照片、视频、音频和文件&#xff0c;以及查找新朋友。但有时候&#xff0c;如果你不小心从你的微信好友列表中删除了某个好友&#xff0c;这可能是因为误操作或者其他原因。在这种情况下&#xff0c;你肯…

【C++学习】异常

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《C学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 异常 &#x1f96e;异常&#x1f362;自定义异常体系&#x1f362;C标准库的异常体系&#x1f362;异…

分享Python采集99个焦点图,总有一款适合您

分享Python采集99个焦点图&#xff0c;总有一款适合您 Python采集的99个焦点图下载链接&#xff1a;https://pan.baidu.com/s/1887LXr2ovCAw-Bp7PuM66g?pwdbyx4 提取码&#xff1a;byx4 原创Jquery焦点图片切换效果 自定义大小&#xff0c;使用方 jquery立体式缩略图焦点图…

CSS样式的三种引入方式及优先级

说明&#xff1a;网页开发有三种技术&#xff0c;分别是html、css和js&#xff0c;分别对应页面的结构、表现和动作。css样式引入&#xff0c;是指把对页面的渲染作用到html上&#xff0c;有以下三种方式&#xff1a;行内式、内嵌式和外联式。 第一种&#xff1a;行内式&#…

每日站会: 保持简短而有效的方法

开发团队对每天的站立会并不陌生。它们在增加协作和可见性方面的成功&#xff0c;促使它们在不同类型的团队和项目中被采用。团队每天都要召开一次站立会&#xff0c;开发人员和其他团队成员将工作目标积极主动地与项目和交付目标保持一致&#xff0c;与团队分享进展情况&#…

剑指offer -- 二维数组中的查找

二维数组中的查找_牛客题霸_牛客网 (nowcoder.com) 暴力查找法: 是一种简单直接的解决方法&#xff0c;可以用于在二维数组中查找目标值。该方法的思路是遍历数组的每个元素&#xff0c;逐个与目标值进行比较。 具体步骤如下&#xff1a; 从数组的第一行第一列开始&#xff0c;…

4、详细版易学版TypeScript - 元组 枚举

一、元组(Tuple) 数组&#xff1a;合并了相同类型的对象 const myArr: Array<number> [1, 2, 3]; 元组(Tuple)&#xff1a;合并了不同类型的对象 // 定义元组时就要确定好数据的类型&#xff0c;并一一对应 const tuple: [number, string] [12, "hi"]; // 添…

ELK日志分析系统

ELK日志分析系统 日志主要包括系统日志/var/log 应用日志 安全日志secure&#xff0c; rsyslog远程传输日志进行汇总集中化管理&#xff0c;日志统计和检索又成为一件比较麻烦的事情&#xff0c;、 1、完整日志系统基本特征 收集&#xff1a;能够采集多种来源的日志数据 …

分布式全局唯一id实现-1DB步长Mybatis-plus雪花算法优化

前言: 开发过程中通常需要一个全局唯一id&#xff0c;对数据进行标识&#xff0c;以便于对数据的统计&#xff0c;因为考虑到主键索引的性能问题&#xff0c;使用数字型效率更高&#xff0c;id 的生成要么借助数据库&#xff0c;要么借助程序内部完成&#xff0c;本文通过数据库…
最新文章