从入门到精通:Java Lambda运算符详解!

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

  在Java 8之前,使用匿名类实现接口是一种常见的编程方式。但是,这种方式往往代码冗长且难以阅读。Java 8引入了Lambda表达式,它提供了一种更简洁的方式来实现接口。Lambda表达式通常是匿名函数(未命名的函数),可以作为参数传递给方法或存储在变量中。在本文中,我们将讨论Lambda表达式的语法、源代码解析、应用场景案例、优缺点分析以及类代码方法介绍。

摘要

  本文将介绍Lambda表达式的基本语法和使用方法,包括源代码解析和应用场景案例。我们还将分析Lambda表达式的优点和缺点,并提供一些测试用例,以帮助读者更好地理解和应用Lambda表达式。

Java之Lambda运算符

简介

  Lambda表达式是Java 8中最重要的新功能之一。它提供了一种简洁而灵活的方式来表示未命名的函数。在Java中,Lambda表达式通常被认为是Java 8中的函数式编程的基础。Lambda表达式的基本语法如下:

(parameters) -> expression

或者

(parameters) -> { statements; }

  其中,parameters是Lambda表达式的参数列表,expression或statements是Lambda表达式的函数体。与常规方法不同,Lambda表达式没有名称。

  Lambda表达式的参数可以为空,也可以包含一个或多个参数。如果参数列表中只有一个参数,则可以省略参数列表的括号。例如:

x -> x + 1 // 接受一个整数参数并返回此参数加1的结果

  Lambda表达式的主要优势在于它提供了一种更简洁的方式来实现接口。在Java 8中,Lambda表达式可以用来实现任何只有一个抽象方法的接口。这种接口被称为函数接口,可以使用@FunctionalInterface注解进行标记。

源代码解析

  让我们来看一个简单的Lambda表达式示例,该示例将接收一个名为names的字符串数组,并将其中的所有元素都转换为大写:

String[] names = {"Alice", "Bob", "Charlie"};
List<String> nameList = Arrays.asList(names);
nameList.stream().map(name -> name.toUpperCase()).forEach(System.out::println);

  在这个例子中,我们使用数组创建了一个名为names的字符串数组,并使用Arrays.asList()方法将其转换为List类型的集合。然后,我们将集合中的每个元素全部转换成大写,并使用forEach()方法对其进行输出。

  从语法上来说,Lambda表达式实际上是一个对象。在Java中,Lambda表达式通常编译成类似于匿名内部类的形式。每个Lambda表达式都有一个与之关联的接口类型,该接口只包含一个未实现的方法。编译器会根据Lambda表达式的参数和返回类型来推断其关联的接口类型。

  下面是一个简单的示例,演示了编写Lambda表达式的过程。

public class LambdaTest {
    public static void main(String[] args) {
        // 无参数的Lambda表达式
        Runnable r = () -> System.out.println("Hello World");
        r.run();
        
        // 有一个参数的Lambda表达式
        Consumer<String> consumer = (s) -> System.out.println(s);
        consumer.accept("Hello World");
        
        // 有两个参数的Lambda表达式
        BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b;
        System.out.println(sum.apply(1, 2));
    }
}

  在这个例子中,我们创建了三个Lambda表达式,其中第一个表达式是一个无参数的Runnable接口实现。第二个表达式使用了一个参数的Consumer接口,该接口接受一个字符串并打印它。第三个表达式使用一个返回整数的BiFunction接口。

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

在这里插入图片描述

代码解析:

  这段代码演示了Lambda表达式的使用,具体分析如下:

  1. 定义了一个无参数的Lambda表达式,使用函数式接口Runnable,通过Lambda表达式实现了run()方法,输出字符串"Hello World"。

  2. 定义了一个有一个参数的Lambda表达式,使用函数式接口Consumer,通过Lambda表达式实现了accept()方法,将传入的字符串打印输出。

  3. 定义了一个有两个参数的Lambda表达式,使用函数式接口BiFunction<T, U, R>,通过Lambda表达式实现了apply()方法,对传入的两个整型数进行相加操作,返回结果。

  在main()方法中,分别创建了这三个Lambda表达式的实例,并分别调用对应的方法输出结果。

应用场景案例

  Lambda表达式可以应用于许多场景。下面是一些常见的应用场景:

  • 集合API:通过使用Lambda表达式,我们可以轻松地对集合中的元素进行过滤、转换和提取等操作。
  • GUI事件处理程序:在JavaFX和Swing等图形用户界面中,可以使用Lambda表达式作为事件处理程序。
  • 并行编程:在Java 8中,我们可以使用Lambda表达式来编写并行代码,从而实现更高效的代码执行。

  下面是一些常见的Lambda表达式应用场景示例:

  • 使用Lambda表达式过滤集合中的元素:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().filter(name -> name.startsWith("A")).forEach(System.out::println);
  • 使用Lambda表达式对集合中的元素进行转换:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().map(name -> name.toUpperCase()).forEach(System.out::println);
  • 使用Lambda表达式作为事件处理程序:
Button button = new Button("Click me");
button.setOnAction(event -> System.out.println("Button clicked"));

代码解析:

  第一个代码示例是使用Lambda表达式对集合进行筛选,使用了Stream API中的filter方法,其中Lambda表达式中使用了startsWith()方法对字符串进行判断,筛选出以"A"开头的字符串并输出。

  第二个代码示例是使用Lambda表达式对集合中的元素进行转换,使用了Stream API中的map方法,其中Lambda表达式中使用了toUpperCase()方法将字符串转换为大写字母并输出。

  第三个代码示例是使用Lambda表达式作为事件处理程序,实现当按钮被点击时输出一条信息。其中Lambda表达式中的代码即为事件发生时要执行的代码。

优缺点分析

  Lambda表达式可以使代码更加简洁、易于阅读和维护。它可以减少代码量、提高程序的可读性和可维护性,同时还能提升程序的性能。Lambda表达式的主要优势在于它提供了一种更简洁的方式来实现接口。在Java 8中,Lambda表达式可以用来实现任何只有一个抽象方法的接口。这种接口被称为函数接口,可以使用@FunctionalInterface注解进行标记。

  然而,Lambda表达式不是完美的。它们可能导致代码变得更加难以理解,特别是在复杂的嵌套情况下。此外,如果Lambda表达式不当使用,可能会导致性能下降和代码可读性降低。

类代码方法介绍

  Lambda表达式可以用于实现函数式接口。下面是一些常见的函数式接口和Lambda表达式的示例:

  • Predicate接口
Predicate<Integer> isEven = n -> n % 2 == 0;
System.out.println(isEven.test(4)); // 输出true
  • Function接口
Function<String, Integer> stringToInt = s -> Integer.parseInt(s);
System.out.println(stringToInt.apply("123")); // 输出123
  • Consumer接口
Consumer<String> printer = s -> System.out.println(s);
printer.accept("Hello World"); // 输出Hello World

代码解析:

  这三个接口都是Java函数式接口,都是Java 8之后引入的,可以用lambda表达式或方法引用来创建函数对象。它们的作用分别如下:

  • Predicate<T>:接收一个泛型参数,返回一个boolean值。用于测试给定的输入值是否符合某种条件,通常用于过滤集合中的元素。
  • Function<T, R>:接收一个泛型参数T,返回一个泛型参数R。用于将一个类型的值转换为另一个类型的值。
  • Consumer<T>:接收一个泛型参数,没有返回值。用于处理给定的输入值,通常用于对集合中的元素执行某些操作。

  在分别实例化了这三个接口之后,可以使用它们提供的方法来执行对应的操作。对于Predicate,可以使用test()方法测试输入值是否符合条件;对于Function,可以使用apply()方法将输入值转换为输出值;对于Consumer,可以使用accept()方法来处理输入值。

测试用例

测试代码演示

package com.example.javase.se.operators;

import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;

/**
 * Java之Lambda运算符实例演示
 *
 * @Author ms
 * @Date 2023-11-08 11:13
 */
public class LambdaDemo {

    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        // 没有参数的Lambda表达式
        Runnable r = () -> System.out.println("Hello World");
        r.run();

        // 有一个参数的Lambda表达式
        Consumer<String> printer = s -> System.out.println(s);
        printer.accept("Hello World");

        // 有两个参数的Lambda表达式
        BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b;
        System.out.println(sum.apply(1, 2));

        // 过滤集合中的元素
        names.stream().filter(name -> name.startsWith("A")).forEach(System.out::println);

        // 将集合中的元素转换为大写
        names.stream().map(name -> name.toUpperCase()).forEach(System.out::println);
    }
}

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

在这里插入图片描述

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。
  该代码演示了Lambda运算符在Java中的使用。Lambda表达式是一种匿名函数,可以作为参数传递给其他方法或函数。Lambda表达式的语法如下:

(parameter1, parameter2, ..., parameterN) -> { statement1; statement2; ... statementN; }

  Lambda表达式的参数可以是0个、1个或多个,类型也可以省略。在示例代码中,展示了Lambda表达式的三种形式:

  1. 没有参数的Lambda表达式:使用Runnable接口创建一个线程并使用Lambda表达式作为其运行代码。

  2. 有一个参数的Lambda表达式:将一条消息作为参数传递给一个消费者函数并使用Lambda表达式打印出来。

  3. 有两个参数的Lambda表达式:将两个整数相加并返回它们的和。

  此外,代码还使用了Java 8中的流API对列表中的元素进行过滤和转换。在过滤集合中元素的示例中,使用了Lambda表达式作为Predicate函数实现,过滤出以字母“A”开头的字符串。在将集合中的元素转换为大写的示例中,使用了Lambda表达式作为Function函数实现,将每个元素转换为大写并打印出来。

全文小结

  首先我们介绍了Lambda表达式的语法、源代码解析、应用场景案例以及优缺点分析。Lambda表达式的语法非常简洁,它可以用来实现任何只有一个抽象方法的接口,这种接口被称为函数接口。

  接着,介绍了Lambda表达式的应用场景,并通过几个代码示例演示了Lambda在集合API、GUI事件处理程序和并行编程中的应用。

  分析了Lambda表达式的优缺点,指出了Lambda表达式可以使代码更加简洁、易于阅读和维护,但也可能会导致代码变得更加难以理解,特别是在复杂的嵌套情况下。

  最后,文章介绍了一些常见的函数式接口和Lambda表达式的示例,并提供了一个包含测试用例的完整代码示例。

  总体来说,本文内容丰富,适合对Lambda表达式感兴趣的Java开发者。

总结

  本文介绍了Java中Lambda表达式的基本语法、源代码解析、应用场景案例、优缺点分析以及类代码方法介绍等内容。Lambda表达式是Java 8中最重要的新功能之一,提供了一种简洁而灵活的方式来表示未命名的函数,可以使代码更加简洁、易于阅读和维护。Lambda表达式的主要优势在于它提供了一种更简洁的方式来实现接口。在Java 8中,Lambda表达式可以用来实现任何只有一个抽象方法的接口,这种接口被称为函数接口。Lambda表达式的应用场景包括集合API、GUI事件处理程序和并行编程等。但是,Lambda表达式也可能会导致代码变得更加难以理解,特别是在复杂的嵌套情况下。本文还提供了一些常见的函数式接口和Lambda表达式的示例,并提供了一个包含测试用例的完整代码示例。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

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

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

相关文章

力扣 48.旋转图像

题目描述&#xff1a; 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],…

Alibbaba RocketMQ笔记

作用场景 异步解耦: 将比较耗时且不需要即时(同步)返回结果 的操作放入消息队列; 流量削峰: 历史简介 基本使用 深入了解\原理

泛型基础及深入

泛型深入 泛型定义&#xff1a; JDK5引入的特性&#xff0c;可以在编译阶段约束操作的数据类型&#xff0c;并进行检查 泛型格式&#xff1a; <数据类型> 注意&#xff1a;泛型只能支持引用数据类型 优势&#xff1a; 统一数据类型&#xff1b; 把运行时期的问题提前到…

JavaWeb_SpringBootWeb案例

环境搭建&#xff1a; 开发规范 接口风格-Restful&#xff1a; 统一响应结果-Result&#xff1a; 开发流程&#xff1a; 第一步应该根据需求定义表结构和定义接口文档 注意&#xff1a; 本文代码从上往下一直添加功能&#xff0c;后面的模块下的代码包括前面的模块&#xff0c…

WPF入门--多种方式设置样式(Style)

前言 在上篇文章中&#xff0c;介绍了WPF九种布局方式。本篇文章通过多种方式设置样式&#xff08;Style&#xff09;以控制UI元素的外观和行为。下面来具体介绍一下。 传送门 WPF入门--常用布局方式 目录 前言 一、直接在XAML中设置属性&#xff08;内联样式&#xff09…

【机器学习】使用Stable Diffusion实现潜在空间搜索

1、引言 1.1 潜在空间的概念 潜在空间&#xff08;Latent Space&#xff09;是在机器学习和深度学习中一个重要的概念&#xff0c;它指的是用于表示数据的一种低维空间。这个空间编码了数据中包含的所有有用信息的压缩表示&#xff0c;通常比原始数据空间的维数更低&#xff…

Python | Leetcode Python题解之第136题只出现一次的数字

题目&#xff1a; 题解&#xff1a; class Solution:def singleNumber(self, nums: List[int]) -> int:return reduce(lambda x, y: x ^ y, nums)

攻防世界---misc---津门杯2021-m1

1、题目描述&#xff0c;下载附件是一张bmp格式的图片 2、直觉告诉我这和图片的颜色通道有关 3、于是我就尝试用stegslove打开图片 4、将颜色通道都改为0&#xff0c;点击preview 5、然后发现一串base64编码 6、解码得flag flag{l5DGqF1pPzOb2LU919LMaBYS5B1G01FD}

CSS真题合集(一)

CSS真题合集&#xff08;一&#xff09; 1. 盒子模型1.1 盒子模型的基本组成1.2 盒子模型的实际大小1.3 盒子模型的两种类型1.4 设置盒子模型1.5 弹性盒子模型 2. BFC2.1 主要用途2.2 触发BFC的方法2.2 解决外边距的塌陷问题&#xff08;垂直塌陷&#xff09; 3. 响应式布局3.1…

某铁路信息中心运营监测项目

某铁路信息中心承担大量实时监测、例行巡检和排障维护等工作&#xff0c;为巩固信息化建设成果&#xff0c;提高整体运维效果&#xff0c;保障铁路信息系统稳定运行&#xff0c;需对现有网络监测系统进行升级改造。 设备类型&#xff1a;服务器、交换机、数据库、中间件、虚拟…

每日一题遇到沙比题目——Python实现PAT甲级1061 Dating(举一反三+思想解读+逐步优化)

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 吐槽题目 我的写法 代码分析 1. 输入处理 2. 变量初始化 3. 查找星期几和小时 4…

Qt for android : 调用 OpenCV库错误集(To Be Continue)

error: error: undefined symbol: AMediaExtractor_new 在调用 VideoCapture等库时出现 解决: LIBS -lmediandk

UE5-AI

AI角色 角色控制器 AI角色必须要一个角色控制器 角色控制器最基本只需要执行行为树&#xff0c;在EventOnPossess后runBehaviorTree 如果要的是一个角色&#xff0c;可以创建一个Character&#xff0c;在类默认设置中可以找到 Pawn->AIControllerClass&#xff0c;在这里…

Golang | Leetcode Golang题解之第136题只出现一次的数字

题目&#xff1a; 题解&#xff1a; func singleNumber(nums []int) int {single : 0for _, num : range nums {single ^ num}return single }

Flink任务如何跑起来之 1.DataStream和Transformation

Flink任务如何跑起来之 1.DataStream和Transformation 1. 滥觞 在使用Flink完成业务功能之余&#xff0c;有必要了解下我们的任务是如何跑起来的。知其然&#xff0c;知其所以然。 既然重点是学习应用程序如何跑起来&#xff0c;那么应用程序的内容不重要&#xff0c;越简单…

动手学深度学习——Kaggle小白入门

1. kaggle注册 注册网址&#xff1a;https://www.kaggle.com 注册账号不需要代理&#xff0c;但手机号验证需要代理。如果要使用GPU或TPU&#xff0c;则需要进行手机号验证。 手机号验证位置&#xff1a;右上角头像的settings界面。 手机号验证时会有几个问题&#xff1a; …

【栈】1096. 花括号展开 II

本文涉及知识点 栈 LeetCode 1096. 花括号展开 II 如果你熟悉 Shell 编程&#xff0c;那么一定了解过花括号展开&#xff0c;它可以用来生成任意字符串。 花括号展开的表达式可以看作一个由 花括号、逗号 和 小写英文字母 组成的字符串&#xff0c;定义下面几条语法规则&…

服务器数据恢复—raid5阵列磁盘坏道离线导致数据丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌x3850 X5服务器&#xff0c;服务器上有一组由5块硬盘组建的raid5阵列&#xff08;包含一块热备盘&#xff09;&#xff0c;安装linux操作系统&#xff0c;运行oracle数据库。 服务器故障&#xff1a; 服务器上raid5阵列中两块硬盘由于未…

【Linux操作系统】进程状态(1)

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; Linux &#x1f389;其它专栏&#xff1a; C初阶 | C进阶 | 初阶数据结构 小伙伴们大家好&#xff0c;本片文章将会讲解 Linux操作系统 进程状态 的相关内容。 如果看到最后您觉得这篇文章…

HDFS 之 DataNode 核心知识点

优质博文&#xff1a;IT-BLOG-CN 一、DataNode工作机制 DataNode工作机制&#xff0c;如下所示&#xff1a; 【1】一个数据块在 DataNode上以文件形式存储在磁盘上&#xff0c;包括两个文件&#xff0c;一个是数据本身&#xff0c;一个是元数据包括数据块的长度&#xff0c…