当前位置: 首页 > news >正文

[JAVA备忘录] Lambda 表达式简单介绍

目录

前言

函数式接口

Lambda 表达式使用实例

简单示例

1. 无参数,无返回值

2. 有参数,无返回值

3. 无参数,有返回值

4. 有参数,有返回值

解释:

集合框架

1.forEach:遍历集合

2.排序:对集合中的元素进行排序

3.映射:将集合中的每个元素转换成另一种形式

4.使用Lambda 表达式定制优先队列

实现函数式接口

         1.Comparator接口

2.Consumer接口

3.Function接口

结尾 


前言

Lambda 表达式 是 Java 8 引入的一项新特性,它使得 Java 编程语言更加简洁、灵活,特别是在处理函数式编程时。Lambda 表达式允许你以一种更加简洁的方式表示匿名函数(即没有名字的函数),它是 Java 对函数式编程思想的支持。    通俗地总结一下,它的作用就是让JAVA代码变得更加简洁.  本文是笔者对它的简单介绍,受制于笔者自身学识的不足,也许有不充分或者错误的地方,在此先说一声抱歉.笔者会经常审阅自己的博客,尽力确保不会有错误.

以下是它的基础语法:

基本语法: (parameters) -> expression 或 (parameters) ->{ statements; }
1. paramaters :类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明 ,也可不声明而由JVM 隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。
2. -> :可理解为 被用于 的意思
3. 方法体 :可以是表达式也可以代码块,是 函数式接口 里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。

函数式接口

首先科普一下什么是函数式接口

1. 如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口
2. 如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接 口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只 有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的。
@FunctionalInterface
interface Example {void test();
}

Lambda 表达式使用实例

简单示例

1. 无参数,无返回值

  如果没有参数, 括号里面也就没有值

@FunctionalInterface
interface NoArgNoReturn {void doSomething();
}public class Main {public static void main(String[] args) {// Lambda 表达式实现接口NoArgNoReturn action = () -> System.out.println("无参数,无返回值的方法执行");// 调用接口方法action.doSomething();}
}

2. 有参数,无返回值

   有参数,所以括号里面要放置我们的参数

@FunctionalInterface
interface WithArgNoReturn {void printMessage(String message);
}public class Main {public static void main(String[] args) {// Lambda 表达式实现接口WithArgNoReturn action = (message) -> System.out.println("Message: " + message);// 调用接口方法action.printMessage("Hello, Lambda!");}
}

3. 无参数,有返回值

 和上面的示例类似

@FunctionalInterface
interface NoArgWithReturn {int getNumber();
}public class Main {public static void main(String[] args) {// Lambda 表达式实现接口NoArgWithReturn action = () -> 42;  // 返回固定的数字// 调用接口方法并打印返回值System.out.println("The number is: " + action.getNumber());}
}

4. 有参数,有返回值

  (括号里面是参数 a,b), 然后我们返回 a+b的值

@FunctionalInterface
interface WithArgsWithReturn {int sum(int a, int b);
}public class Main {public static void main(String[] args) {// Lambda 表达式实现接口WithArgsWithReturn action = (a, b) -> a + b;  // 返回两个数的和// 调用接口方法并打印返回值System.out.println("The sum is: " + action.sum(10, 20));}
}

这么做简化在哪里呢?请看如下例子

import java.util.*;@FunctionalInterface
interface Example {void test();
}
public class Main {public static void main(String[] args) {Example example = new Example() {@Overridepublic void test() {System.out.println("这是一个示例");}};example.test();}
}

我们这里定义了一个接口 Example,然后在 main 方法中创建了一个匿名内部类实现了 Example 接口。这个匿名类的实现是通过 new Example() {} 来完成的。 所以对比能发现,使用Lambda确实可以简化代码.

解释:

匿名内部类(Anonymous Inner Class)是一个没有名字的类,通常在实例化时使用。它是类的一个局部实现,可以用来简化代码,尤其在只需要某个接口的一个临时实现时。

集合框架

1.forEach:遍历集合

List<String> list = Arrays.asList("apple", "banana", "cherry");
list.forEach(item -> System.out.println(item));


2.排序:对集合中的元素进行排序

List<Integer> numbers = Arrays.asList(5, 3, 1, 4, 2);
numbers.sort((a, b) -> a - b);  // 使用 Lambda 表达式进行升序排序
numbers.forEach(System.out::println);  // 输出: 1, 2, 3, 4, 5

3.映射:将集合中的每个元素转换成另一种形式
 

List<String> strings = Arrays.asList("apple", "banana", "cherry");
strings.stream().map(String::toUpperCase)  // 将字符串转为大写.forEach(System.out::println);

4.使用Lambda 表达式定制优先队列

我们在使用PriorityQueue时,通常需要定义这是大根堆还是小根堆,我们可以使用Lambda表达式来简化这个过程

PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((o1, o2) -> o1-o2);PriorityQueue<Integer> priorityQueue1 = new PriorityQueue<>(new Comparator<Integer>() 
{@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;}
});
顺便提一嘴,这个操作为什么list不行呢?因为根据两者的源代码来看

PriorityQueue 实现了比较接口,它能够根据你提供的比较规则(Comparator)来排序元素,或者通过元素自身的自然顺序(如果元素实现了 Comparable 接口)来排序。因此,它支持自动排序。

    public PriorityQueue(Comparator<? super E> comparator) {this(DEFAULT_INITIAL_CAPACITY, comparator);}

List 不直接实现比较接口,它是一个普通的集合类,维护元素的插入顺序。要对 List 中的元素进行排序,必须显式地调用排序方法(比如 list.sort()),并提供一个 Comparator 或让元素实现 Comparable 接口。

public interface List<E> extends Collection<E>

笔者这里也是随意的举几个例子,读者们明白意思就好.

实现函数式接口

Lambda 实现函数式接口也是它的重要功能,笔者接下来举几个例子给读者看看

1.Comparator接口

如果正常地使用该接口,应该是这样的

import java.util.*;class Person {String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return name + ": " + age;}
}public class Main {public static void main(String[] args) {List<Person> people = new ArrayList<>();people.add(new Person("Alice", 30));people.add(new Person("Bob", 25));people.add(new Person("Charlie", 35));// 使用自定义 Comparator 按照年龄排序people.sort(new Comparator<Person>() {@Overridepublic int compare(Person o1, Person o2) {return o1.age - o2.age;  // 按照年龄升序排序}});// 输出排序后的列表for (Person person : people) {System.out.println(person);}}
}

如果使用Lambda 表达式,可以简化为

import java.util.*;public class Main {public static void main(String[] args) {List<Person> people = new ArrayList<>();people.add(new Person("Alice", 30));people.add(new Person("Bob", 25));people.add(new Person("Charlie", 35));// 使用 Lambda 表达式按年龄排序people.sort((o1, o2) -> o1.age - o2.age);// 输出排序后的列表for (Person person : people) {System.out.println(person);}}
}

小科普:为什么它是函数式接口

我们透过Comparator接口的源码可以看到

 boolean equals(Object obj);

 他其实还有这么方法,那么这是为什么呢?

答:  这是从 Object 类继承的,不属于接口本身定义的抽象方法。

根据 Java 的定义,函数式接口的判断依据是其抽象方法的数量,而不是它是否包含其他默认方法或静态方法。

  1. 继承自 Object 的方法不计入抽象方法
    equals() 是所有类(包括接口)的通用方法,它属于 Object 类,不是 Comparator 定义的抽象方法。

  2. 默认方法和静态方法不影响函数式接口的定义
    Java 8 引入默认方法和静态方法后,它们提供了更多的工具和扩展性,但这些都不影响抽象方法的唯一性。

因此,Comparator 只有一个抽象方法 compare(T o1, T o2),符合函数式接口的定义。

2.Consumer接口

以下是我的例子:

  List<String> list1 = new ArrayList<>();list1.add("niko");list1.add("bit");list1.add("ropz");list1.add("faker");list1.add("lwx");list1.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});list.forEach((s -> System.out.println(s)));

3.Function接口

 Function<Integer,Integer> function = x-> x *5;System.out.println(function.apply(2));
 Function<Integer,Integer> function = new Function<Integer, Integer>() {@Overridepublic Integer apply(Integer integer) {return integer*5;}};System.out.println(function.apply(2));

结尾 

我不敢恬不知耻地说这是一遍综合介绍Lambda 表达式的博客,因为受制于自身知识有限,我没有完整地拿出很多例子.但我可以说它初步介绍了Lambda 表达式,希望能给阅读到的小白一些总结性的思考.

相关文章:

[JAVA备忘录] Lambda 表达式简单介绍

目录 前言 函数式接口 Lambda 表达式使用实例 简单示例 1. 无参数&#xff0c;无返回值 2. 有参数&#xff0c;无返回值 3. 无参数&#xff0c;有返回值 4. 有参数&#xff0c;有返回值 解释&#xff1a; 集合框架 1.forEach&#xff1a;遍历集合 2.排序&#xff1…...

[python]使用flask-caching缓存数据

简介 Flask-Caching 是 Flask 的一个扩展&#xff0c;为任何 Flask 应用程序添加了对各种后端的缓存支持。它基于 cachelib 运行&#xff0c;并通过统一的 API 支持 werkzeug 的所有原始缓存后端。开发者还可以通过继承 flask_caching.backends.base.BaseCache 类来开发自己的…...

裸机按键输入实验

一、硬件原理分析 按键就两个状态&#xff1a;按下或弹起&#xff0c;将按键连接到一个 IO 上&#xff0c;通过读取这个 IO 的值就知道按 键是按下的还是弹起的。至于按键按下的时候是高电平还是低电平要根据实际电路来判断。前 面几章我们都是讲解 I.MX6U 的 GPIO 作为输出使用…...

GaussDB运维管理工具(二)

GaussDB运维管理工具&#xff08;二&#xff09; 集群管理组件cm_ctl工具介绍cm_ctl工具使用查询集群状态启停集群主备切换重建备DN检测进程运行查看实例配置文件手动剔除故障CNCM参数获取和配置停止仲裁 Cluster Manager&#xff08;缩写为CM&#xff09;是GaussDB的集群管理工…...

【HarmonyOS之旅】HarmonyOS开发基础知识(一)

目录 1 -> 应用基础知识 1.1 -> 用户应用程序 1.2 -> 用户应用程序包结构 1.3 -> Ability 1.4 -> 库文件 1.5 -> 资源文件 1.6 -> 配置文件 1.7 -> pack.info 1.8 -> HAR 2 -> 配置文件简介 2.1 -> 配置文件的组成 3 -> 配置文…...

Mysql数据究竟是如何存储的

Mysql行列式 开篇 ​ 笔者这几日在学习mysql是这么运行的这本书&#xff0c;感觉书中的内容受益匪浅&#xff0c;想整理成自己的话分享给大家&#xff0c;平时大家工作和生活中可能没有时间去专心投入读取一本书&#xff0c;而mysql是这么运行的这本书需要投入大量的时间的学…...

STM32单片机使用CAN协议进行通信

CAN总线&#xff08;控制器局域网总线&#xff09; 理论知识 CAN总线是由BOSCH公司开发的一种简洁易用、传输速度快、易扩展、可靠性高的串行通信总线 CAN总线特征 两根通信线&#xff08;CAN_H、CAN_L&#xff09;&#xff0c;线路少&#xff0c;无需共地差分信号通信&…...

Docker 入门:如何使用 Docker 容器化 AI 项目(二)

四、将 AI 项目容器化&#xff1a;示例实践 - 完整的图像分类与 API 服务 让我们通过一个更完整的 AI 项目示例&#xff0c;展示如何将 AI 项目容器化。我们以一个基于 TensorFlow 的图像分类模型为例&#xff0c;演示如何将训练、推理、以及 API 服务过程容器化。 4.1 创建 …...

MVVM、MVC、MVP 的区别

MVVM&#xff08;Model-View-ViewModel&#xff09;、MVC&#xff08;Model-View-Controller&#xff09;和MVP&#xff08;Model-View-Presenter&#xff09;是三种常见的软件架构模式&#xff0c;它们在客户端应用开发中被广泛使用。每种模式都有其特定的设计理念和应用场景&…...

【Verilog】期末复习

数字逻辑电路分为哪两类&#xff1f;它们各自的特点是什么&#xff1f; 组合逻辑电路&#xff1a;任意时刻的输出仅仅取决于该时刻的输入&#xff0c;而与电路原来的状态无关 没有记忆功能&#xff0c;只有从输入到输出的通路&#xff0c;没有从输出到输入的回路 时序逻辑电路&…...

C#都可以找哪些工作?

在国内学习C#&#xff0c;可以找的工作主要是以下4个&#xff1a; 1、游戏开发 需要学习C#编程、Unity引擎操作、游戏设计和3D图形处理等。 2、PC桌面应用开发 需要学习C#编程、WinForm框架/WPF框架、MVVM设计模式和UI/UX设计等。 3、Web开发 需要学习C#编程、ASP.NET框架…...

机器学习Python使用scikit-learn工具包详细介绍

一、简介 Scikit-learn是一个开源的机器学习库&#xff0c;用于Python编程语言。它建立在NumPy、SciPy和matplotlib这些科学计算库之上&#xff0c;提供了简单有效的数据挖掘和数据分析工具。Scikit-learn库包含了许多用于分类、回归、聚类和降维的算法&#xff0c;包括支持向量…...

蓝桥杯真题 - 扫雷 - 题解

题目链接&#xff1a;https://www.lanqiao.cn/problems/549/learning/ 个人评价&#xff1a;难度 1 星&#xff08;满星&#xff1a;5&#xff09; 前置知识&#xff1a;无 整体思路 按题意模拟&#xff1b;为了减少不必要的“数组越界”判断&#xff0c;让数组下标从 1 1 1…...

vue3项目结合Echarts实现甘特图(可拖拽、选中等操作)

效果图&#xff1a; 图一&#xff1a;选中操作 图二&#xff1a;上下左右拖拽操作 本案例在echarts​​​​​​​示例机场航班甘特图的基础上修改​​​​​​​ 封装ganttEcharts组件&#xff0c;测试数据 airport-schedule.jsonganttEcharts代码: 直接复制粘贴可测​​​​…...

Log4j2 插件的简单使用

代码: TestPlugin.java package com.chenjiacheng.webapp.plugins;import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.lookup.StrLookup;/*** Created by chenjiacheng on …...

Linux之RPM和YUM命令

一、RPM命令 1、介绍 RPM(RedHat Package Manager).,RedHat软件包管理工具&#xff0c;类似windows里面的setup,exe是Liux这系列操作系统里而的打包安装工具。 RPMI包的名称格式&#xff1a; Apache-1.3.23-11.i386.rpm “apache’” 软件名称“1.3.23-11” 软件的版本号&am…...

读取硬件板子上的数据

SSCOM工具&#xff0c;先要安装一个插件 这样就可以读到设备数据...

Cesium 实例化潜入潜出

Cesium 实例化潜入潜出 1、WebGL Instance 的原理 狭义的的WebGL 中说使用 Instance, 一般指使用 glDrawArraysInstanced 用于实例化渲染的函数。它允许在一次绘制调用中渲染多个相同的几何体实例&#xff0c;而无需为每个实例发起单独的绘制调用。 Three.js 就是使用这种方…...

java引入jedis并且关于开放redis端口问题

博主主页: 码农派大星. 数据结构专栏:Java数据结构 数据库专栏:数据库 JavaEE专栏:JavaEE 软件测试专栏:软件测试 关注博主带你了解更多知识 目录 1. 引入jedis ​编辑 2. 关于java客户端开放redis端口问题 3. 连接redis服务器 redis服务器在官网公开了使用的协议: resp…...

【人工智能】用Python实现情感分析:从简单词典到深度学习方法的演进

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 情感分析是自然语言处理(NLP)中的一个重要任务,其目的是通过分析文本内容,识别出其中的情感极性,如正面、负面或中性。随着技术的不断…...

CD3抗体如何成为双抗药物的核心靶点?

一、双特异性抗体药物为何发展迅猛&#xff1f;双特异性抗体&#xff08;BsAb&#xff09;是一类能够同时特异性结合两个不同抗原或抗原表位的人工工程抗体。其通过同时阻断两个靶点介导的生物学功能&#xff0c;或将表达不同抗原的细胞拉近&#xff0c;实现单一抗体难以完成的…...

Windows加域必看:如何用PowerShell一键指定OU路径(附完整代码)

Windows域管理自动化&#xff1a;PowerShell指定OU路径的终极指南 在大型企业IT环境中&#xff0c;计算机加域操作从来不是单次事件&#xff0c;而是需要批量执行的常规运维任务。传统手动操作不仅效率低下&#xff0c;还容易因人为失误导致计算机被放入错误的组织单元(OU)。想…...

【Python】安装 Python 环境

需要安装的环境主要是两个部分&#xff1a; 运行环境&#xff1a;Python开发环境&#xff1a;PyCharm 一、安装 Python 1、找到官方网站 Welcome to Python.org 2、找到下载页面 选择 "Download for Windows"&#xff1a; 现在主流使用的 Python 版本是 Python…...

PyTorch 2.8镜像保姆级教程:RTX 4090D下HuggingFace Datasets高效加载

PyTorch 2.8镜像保姆级教程&#xff1a;RTX 4090D下HuggingFace Datasets高效加载 1. 环境准备与快速验证 1.1 镜像基本信息确认 本教程使用的PyTorch 2.8镜像已针对RTX 4090D显卡进行深度优化&#xff0c;主要配置如下&#xff1a; 核心组件&#xff1a;PyTorch 2.8 CUDA…...

企业财务系统集成指南:如何用诺诺开放平台API搞定电子发票全流程(从签约到开票)

企业财务系统集成指南&#xff1a;诺诺开放平台电子发票全流程实战 当财务数字化转型成为企业降本增效的刚需&#xff0c;电子发票作为交易闭环的关键环节&#xff0c;其系统集成质量直接影响业务流畅度。本文将带您全景式拆解从商务对接到技术落地的完整链路&#xff0c;避开那…...

大多数人手动给Agent加记忆 Meta HyperAgents却让AI自己发明了完整记忆系统

你是不是也这样造Agent&#xff1a;先搭好任务执行模块&#xff0c;再手动塞一个向量数据库或RAG当记忆&#xff0c;最后发现跨轮迭代时效果还是“每次从零开始”&#xff1f;性能没 compounding&#xff0c;跨任务迁移更是一团乱麻。明明AI已经能自我迭代了&#xff0c;为什么…...

行波管(TWT)核心参数权衡:填充比、流通率与电子注效率的物理本质及工程设计

在行波管&#xff08;TWT&#xff09;设计中&#xff0c;填充比&#xff08;F&#xff09;、流通率&#xff08;ηₜᵣₐₙₛ&#xff09;与电子注效率&#xff08;ηₑ&#xff09;是决定器件性能的三大核心参数&#xff0c;三者并非独立存在&#xff0c;而是形成了紧密的物理…...

使用MATLAB进行DeOldify结果的后处理与定量分析

使用MATLAB进行DeOldify结果的后处理与定量分析 如果你是一位习惯在MATLAB环境中工作的研究人员或工程师&#xff0c;当你想对DeOldify这类AI图像上色工具的输出结果进行更深入的评估时&#xff0c;可能会觉得缺少趁手的分析工具。直接看效果图固然直观&#xff0c;但如何量化…...

IntelliJ IDEA 2026.1 版本发布,多维度升级助力开发体验

AI 能力拓展&#xff1a;内置多 Agent 提升开发效率IntelliJ IDEA 2026.1 版本在 AI 方面有显著升级&#xff0c;内置支持更多 AI agent&#xff0c;如 Codex、Cursor 以及任何兼容 ACP 的 agent。ACP Registry 实现了一键浏览和安装 AI agent&#xff0c;方便开发者快速引入所…...

VRCT终极指南:3步实现VRChat跨语言实时翻译,打破虚拟社交障碍

VRCT终极指南&#xff1a;3步实现VRChat跨语言实时翻译&#xff0c;打破虚拟社交障碍 【免费下载链接】VRCT VRCT(VRChat Chatbox Translator & Transcription) 项目地址: https://gitcode.com/gh_mirrors/vr/VRCT 您是否曾在VRChat的国际房间中&#xff0c;面对来自…...