0

0

Java的Lambda表达式使用实例分析

WBOY

WBOY

发布时间:2023-04-18 16:01:03

|

1025人浏览过

|

来源于亿速云

转载

lambada 简介

lambda 表达式 是java 8新加入的新特性,它在java中是引入了函数式编程这一概念。那么什么是函数式编程呢?

函数式编程:函数式编程是面向数学的抽象,将计算描述为一种表达式求值。

我们平常所说的面向对象编程属于命令式编程,函数式编程和命令式编程的区别是:

  • 函数式编程关心数据的映射,命令式编程关系解决问题的步骤。

  • 函数式编程关系类型(代数结构)之间的关系,命令式编程关系解决问题的步骤。

函数式编程的本质:

立即学习Java免费学习笔记(深入)”;

函数式编程中的函数指的不是计算机中的函数,而是数学中的函数,即自变量的映射。即:一个函数的值仅取决于函数参数的值,不依赖其他状态。

严格意义上的函数式编程意味着不使用可变的变量,赋值,循环和其他命令式控制结构进行编程。

函数式编程的好处:

函数式编程的好处是主要是不可变性带来的。没有可变的状态,函数就是引用透明(Referential transparency)的和没有副作用的(No Side Effect)。

上面这些都是一些基本的概念,但是我们平时可能接触这些方面的东西比较少,所以一开始感觉函数式编程是很难得东西。

简单的示例

Talk is cheap, show me the code!

先来一个最简单的例子,可能也是介绍的最多的例子了。哈哈!

给按钮添加监视器。

使用匿名内部类的方式,进行添加。

submit.addActionListener(new ActionListener() {
	@Override
	public void actionPerformed(ActionEvent e) {
		JOptionPane.showMessageDialog(null, "点击了确定按钮", "确定", JOptionPane.INFORMATION_MESSAGE);
	}
});

这种方式的缺点:使用了很多的模板代码,真正必要的代码,只是方法体内的代码。所以,Java 8 引入的 Lambda 表达式可以简化这种代码(当然了,也是有限制的,不是所有的匿名内部类都可以,这个后面会提到。)。

使用 Lambda 表达式 简化代码

submit.addActionListener((e)->{
		JOptionPane.showMessageDialog(null, "点击了确定按钮", "确定", JOptionPane.INFORMATION_MESSAGE);
});

Lambda 表达式是一个匿名方法,将行为像数据一样进行传递。

说明

可以看出来,使用 Lambda 表达式简化后的代码表达变得更加清晰了,并且不用再去写繁琐的模板代码了。

进一步简化

参数括号和代码体的花括号也可以省略(只有一个参数时,可以省略圆括号,只有一行代码时,可以省略花括号)。

ActionListener listener = e->JOptionPane.showMessageDialog(null, "点击了确定按钮", "确定", JOptionPane.INFORMATION_MESSAGE);

小结
当使用 Lambda 表达式代替匿名内部类创建对象时,Lambda 表达式的代码块将会替代实现抽象方法的方法体,Lambda 就相当于一个匿名方法。

Lambda 表达式的组成部分

lambda 表达式由三部分组成:

  • 形参列表。形参列表允许省略形参类型。如果形参列表中只有一个参数,可以省略形参列表的圆括号。

  • 箭头(->)。英文短线和大于号。

  • 代码块。如果代码块只有一句,可以省略花括号。如果只有一条 return 语句,可以省略 return,lambda表达式会自动返回这条语句的值。

注:
之所以可以省略形参列表是因为 编译器 可以进行类型推断,例如:

List<Dog> dogs1 = new ArrayList<Dog>();

List<Dog> dogs2 = new ArrayList<>();

上面使用 菱形语法,可以省略尖括号里面的东西,这就是类型推断的作用
但是类型推断也不是万能的,不是所有的都可以推断出来的,所以有时候,还是要显示的添加形参类型,例如:

先不要管这个代码的具体作用。

BinaryOperator b = (x, y)->x*y;
//上面这句代码无法通过编译,下面是报错信息:无法将 * 运算符作用于 java.lang.Object 类型。
The operator * is undefined for the argument type(s) java.lang.Object, java.lang.Object
//添加参数类型,正确的代码。
BinaryOperator<Integer> b = (x, y)->x*y;

所以,类型推断不是万能的,如果编译器无法推断,那就是我们的错误,不要过度依赖编译器。有时候,显示的添加参数类型,还是很必要的,当然了,这需要去多练习。

函数式接口

前面了解了,Lambda 表达式可以代替匿名内部类,进而达到简化代码,表达清晰的目的。那么使用 Lambda 表示式的前提是什么呢?-- 函数式接口

Lambda 表达式的类型,也被称为 目标类型 (Target Type),它必须是一个函数式接口(Functional Interface)。所谓函数式接口,指的就是:只包含一个抽象方法的接口。(可以包含多个默认方法,静态方法,但必须只有一个抽象方法)。
注:Java 8 专门提供了一个注解:@FunctionalInterface。用于标注某个接口是函数式接口,这样编译时就会检查,如果该接口含有多个抽象方法,编译器就会报错。

上面使用 Lambda 表达式来为按钮添加了监视器,可以看出来,Lambda 表达式 代替了 new ActionListener()对象。

所以 Lambda 的表达式就是被当成一个对象。

例如:

ActionListener listener = e->JOptionPane.showMessageDialog(null, "点击了确定按钮", "确定", JOptionPane.INFORMATION_MESSAGE);

从上面这个例子中可以看出来,Lambda 表达式实现的是匿名方法–因此它只能实现特定函数式接口中的唯一方法。
所以 Lambda 表达式有下面两种限制:

Lambda 表达式的目标类型必须是明确的函数式接口。 Lambda 表达式只能为函数式接口创建对象。Lambda只能实现一个方法,因此它只能为含有一个抽象方法的接口(函数式接口)创建对象。 介绍几个 Java 中重要的函数接口

Java的Lambda表达式使用实例分析

从这种表可以看出来,抽象方法的名字反而不是最重要的了,重要的是参数和返回值。 因为在写 Lambda 表达式的时候,也不要使用 抽象方法名了。

上面使用几个简单的例子来说明上面接口的应用:

测试代码

import java.text.ParseException;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;

public class Test {
	public static void main(String[] args) throws ParseException {
		//Lambda 表达式中的构造器引用,用于简化代码。
		Creat<Dog> c = Dog::new;
		Dog dog = c.creat("小黑", 15);
		System.out.println(dog.toString());
		
		Predicate<String> predicate = (words)->{
			return words.length() > 20;
		};
		assert predicate.test("I love you yesterday and today!") : "长度小于20";
		assert !predicate.test("God bless you!") : "长度小于20";
		System.out.println("------------------------");
		
		Consumer<Dog> consumer = System.out::println;
		consumer.accept(dog);
		System.out.println("------------------------");

		Function<Dog, String> function = (dogObj)->{
			return dogObj.getName();
		};
		System.out.println(function.apply(dog));
		System.out.println("------------------------");
		
		Supplier<Dog> supplier = ()->{
			return new Dog("大黄", 4);
		};
		System.out.println(supplier.get());
		
		//一元操作符
		UnaryOperator<Boolean> unaryOperation = (flag)->{
			return !flag;
		};
		System.out.println(unaryOperation.apply(true));
		
		BinaryOperator<Integer> binaryOperator = (x, y)->x*y;
		int result = binaryOperator.apply(999, 9999);
		System.out.println(result);
	}
}

测试使用的实体类

public class Dog {
	private String name;
	private int age;
	
	public Dog(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Dog [name=" + name + ", age=" + age + "]";
	}
}

自定义函数式接口

@FunctionalInterface
public interface Creat<T> {
	public T creat(String name, int age);
}

运行截图就不放了,感兴趣的可以试一下。

说明
我这里直接使用 Lambda 创建了对象,然后调用了这个对象的方法(就是lambda 的代码块部分),真正使用的时候,都是直接传递 Lambda 表达式的,这种方法并不推荐,但是可以让我们很好的理解为什么? 可以看出来,Lambda 表达式的作用,最后还是需要调用 重写的抽象方法的,只不过使用表达更加清晰,简化了代码。

例如:

		List<Dog> dogs = new ArrayList<>();
		dogs.add(new Dog("大黄", 2));
		dogs.add(new Dog("小黑", 3));
		dogs.add(new Dog("小哈",1));
		//将行为像数据一样传递,使用集合的 forEach 方法来遍历集合,
		//参数可以是一个 Lambda 表达式。
		Consumer<? super Dog> con = (e)->{
			System.out.println(e);
		};
		dogs.forEach(con);
		System.out.println("--------------------------\n");
	
		//直接传递 Lambda 表达式,更加简洁
		dogs.forEach(e->System.out.println(e));
		System.out.println("--------------------------\n");

		//使用方法引用,进一步简化(可以看我的另一篇关于方法引用的博客)
		dogs.forEach(System.out::println);
		System.out.println("--------------------------\n");

		//使用 Lambda 对集合进行定制排序,按照年龄排序(从小到大)。
		dogs.sort((e1, e2)->e1.getAge()-e2.getAge());
		dogs.forEach(System.out::println);

可以看出来,通过使用 Lambda 表达式可以,极大的简化代码,更加方便的操作集合。值得一提的是:Lambda 表达式 和 Stream 的结合,可以拥有更加丰富的操作,这也是下一步学习的方向。

运行截图:

Java的Lambda表达式使用实例分析

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

16

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

23

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

75

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

95

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

218

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

420

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

168

2026.03.04

Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

222

2026.03.03

C++高性能网络编程与Reactor模型实践
C++高性能网络编程与Reactor模型实践

本专题围绕 C++ 在高性能网络服务开发中的应用展开,深入讲解 Socket 编程、多路复用机制、Reactor 模型设计原理以及线程池协作策略。内容涵盖 epoll 实现机制、内存管理优化、连接管理策略与高并发场景下的性能调优方法。通过构建高并发网络服务器实战案例,帮助开发者掌握 C++ 在底层系统与网络通信领域的核心技术。

33

2026.03.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.3万人学习

C# 教程
C# 教程

共94课时 | 11.1万人学习

Java 教程
Java 教程

共578课时 | 80.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号