Java8深入学习系列(一)lambda表达式介绍
发布时间 - 2026-01-11 02:42:32 点击率:次前言

最近在学习java8,所以接下来会给大家介绍一系列的Java8学习内容,那么让我们先从lambda表达式开始。
众所周知从java8出现以来lambda是最重要的特性之一,它可以让我们用简洁流畅的代码完成一个功能。 很长一段时间java被吐槽是冗余和缺乏函数式编程能力的语言,随着函数式编程的流行java8种也引入了 这种编程风格。在此之前我们都在写匿名内部类干这些事,但有时候这不是好的做法,本文中将介绍和使用lambda, 带你体验函数式编程的魔力。
什么是lambda?
lambda表达式是一段可以传递的代码,它的核心思想是将面向对象中的传递数据变成传递行为。 我们回顾一下在使用java8之前要做的事,之前我们编写一个线程时是这样的:
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("do something.");
}
}
也有人会写一个类去实现Runnable接口,这样做没有问题,我们注意这个接口中只有一个run方法, 当把Runnable对象给Thread对象作为构造参数时创建一个线程,运行后将输出do something. 。 我们使用匿名内部类的方式实现了该方法。
这实际上是一个代码即数据的例子,在run方法中是线程要执行的一个任务,但上面的代码中任务内容已经被规定死了。 当我们有多个不同的任务时,需要重复编写如上代码。
设计匿名内部类的目的,就是为了方便 Java 程序员将代码作为数据传递。不过,匿名内部 类还是不够简便。 为了执行一个简单的任务逻辑,不得不加上 6 行冗繁的样板代码。那如果是lambda该怎么做?
Runnable r = () -> System.out.println("do something.");
嗯,这代码看起来很酷,你可以看到我们用()和->的方式完成了这件事,这是一个没有名字的函数,也没有人和参数,再简单不过了。 使用->将参数和实现逻辑分离,当运行这个线程的时候执行的是->之后的代码片段,且编译器帮助我们做了类型推导; 这个代码片段可以是用{}包含的一段逻辑。下面一起来学习一下lambda的语法。
基础语法
在lambda中我们遵循如下的表达式来编写:
expression = (variable) -> action
- variable: 这是一个变量,一个占位符。像x,y,z,可以是多个变量。
- action: 这里我称它为action, 这是我们实现的代码逻辑部分,它可以是一行代码也可以是一个代码片段
可以看到Java中lambda表达式的格式:参数、箭头、以及动作实现,当一个动作实现无法用一行代码完成,可以编写 一段代码用{}包裹起来。
lambda表达式可以包含多个参数,例如:
int sum = (x, y) -> x + y;
这时候我们应该思考这段代码不是之前的x和y数字相加,而是创建了一个函数,用来计算两个操作数的和。 后面用int类型进行接收,在lambda中为我们省略去了return。
函数式接口
函数式接口是只有一个方法的接口,用作lambda表达式的类型。前面写的例子就是一个函数式接口,来看看jdk中的Runnable源码
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
这里只有一个抽象方法run,实际上你不写public abstract也是可以的,在接口中定义的方法都是public abstract的。 同时也使用注解@FunctionalInterface告诉编译器这是一个函数式接口,当然你不这么写也可以,标识后明确了这个函数中 只有一个抽象方法,当你尝试在接口中编写多个方法的时候编译器将不允许这么干。
尝试函数式接口
我们来编写一个函数式接口,输入一个年龄,判断这个人是否是|成人|。
public class FunctionInterfaceDemo {
@FunctionalInterface
interface Predicate<T> {
boolean test(T t);
}
/**
* 执行Predicate判断
*
* @param age 年龄
* @param predicate Predicate函数式接口
* @return 返回布尔类型结果
*/
public static boolean doPredicate(int age, Predicate<Integer> predicate) {
return predicate.test(age);
}
public static void main(String[] args) {
boolean isAdult = doPredicate(20, x -> x >= 18);
System.out.println(isAdult);
}
}
从这个例子我们很轻松的完成 是否是|成人| 的动作,其次判断是否是|成人|,在此之前我们的做法一般是编写一个 判断是否是|成人|的方法,是无法将 判断 共用的。而在本例只,你要做的是将 行为 (判断是否是|成人|,或者是判断是否大于30岁) 传递进去,函数式接口告诉你结果是什么。
实际上诸如上述例子中的接口,伟大的jdk设计者为我们准备了java.util.function包
我们前面写的Predicate函数式接口也是JDK种的一个实现,他们大致分为以下几类:
| 接口 | 参数 | 返回值 | 类别 | 示例 |
|---|---|---|---|---|
| Consumer |
T | void | 消费型接口 | 输出一个值 |
| Supplier |
None | T | 供给型接口 | 工厂方法 |
| Function | T | R | 函数型接口 | 获得 Artist 对象的名字 |
| Predicate |
T | boolean | 断言型接口 | 这张唱片已经发行了吗 |
消费型接口示例
public static void donation(Integer money, Consumer<Integer> consumer){
consumer.accept(money);
}
public static void main(String[] args) {
donation(1000, money -> System.out.println("好心的麦乐迪为Blade捐赠了"+money+"元")) ;
}
供给型接口示例
public static List<Integer> supply(Integer num, Supplier<Integer> supplier){
List<Integer> resultList = new ArrayList<Integer>() ;
for(int x=0;x<num;x++)
resultList.add(supplier.get());
return resultList ;
}
public static void main(String[] args) {
List<Integer> list = supply(10,() -> (int)(Math.random()*100));
list.forEach(System.out::println);
}
函数型接口示例
转换字符串为Integer
public static Integer convert(String str, Function<String, Integer> function) {
return function.apply(str);
}
public static void main(String[] args) {
Integer value = convert("28", x -> Integer.parseInt(x));
}
断言型接口示例
筛选出只有2个字的水果
public static List<String> filter(List<String> fruit, Predicate<String> predicate){
List<String> f = new ArrayList<>();
for (String s : fruit) {
if(predicate.test(s)){
f.add(s);
}
}
return f;
}
public static void main(String[] args) {
List<String> fruit = Arrays.asList("香蕉", "哈密瓜", "榴莲", "火龙果", "水蜜桃");
List<String> newFruit = filter(fruit, (f) -> f.length() == 2);
System.out.println(newFruit);
}
默认方法
在Java语言中,一个接口中定义的方法必须由实现类提供实现。但是当接口中加入新的API时, 实现类按照约定也要修改实现,而Java8的API对现有接口也添加了很多方法,比如List接口中添加了sort方法。 如果按照之前的做法,那么所有的实现类都要实现sort方法,JDK的编写者们一定非常抓狂。
幸运的是我们使用了Java8,这一问题将得到很好的解决,在Java8种引入新的机制,支持在接口中声明方法同时提供实现。 这令人激动不已,你有两种方式完成 1.在接口内声明静态方法 2.指定一个默认方法。
我们来看看在JDK8中上述List接口添加方法的问题是如何解决的
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
翻阅List接口的源码,其中加入一个默认方法default void sort(Comparator<? super E> c) 。 在返回值之前加入default关键字,有了这个方法我们可以直接调用sort方法进行排序。
List<Integer> list = Arrays.asList(2, 7, 3, 1, 8, 6, 4); list.sort(Comparator.naturalOrder()); System.out.println(list);
Comparator.naturalOrder()是一个自然排序的实现,这里可以自定义排序方案。 你经常看到使用Java8操作集合的时候可以直接foreach的原因也是在Iterable接口中也新增了一个默认方法:forEach , 该方法功能和 for 循环类似,但是允许 用户使用一个Lambda表达式作为循环体。
在后面的章节中我们再次通过案例来展示函数式编程的魅力 :)
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
# java8
# lambda表达式
# lambda
# java8的lambda表达式
# JAVALambda表达式与函数式接口详解
# 浅析Java8新特性Lambda表达式和函数式接口
# 一文带你掌握Java8中Lambda表达式 函数式接口及方法构造器数组的引用
# Java Lambda表达式和函数式接口实例分析
# lambda表达式与传统接口函数实现方式对比详解
# 多个
# 的是
# 是一个
# 只有一个
# 判断是否
# 这是
# 一个函数
# 让我们
# 在此
# 这是一个
# 要做
# 它可以
# 返回值
# 都是
# 这一
# 是在
# 也有
# 很好
# 去了
# 过了
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
java ZXing生成二维码及条码实例分享
音乐网站服务器如何优化API响应速度?
Laravel的辅助函数有哪些_Laravel常用Helpers函数提高开发效率
Laravel如何安装Breeze扩展包_Laravel用户注册登录功能快速实现【流程】
弹幕视频网站制作教程下载,弹幕视频网站是什么意思?
大连网站制作公司哪家好一点,大连买房网站哪个好?
Laravel怎么解决跨域问题_Laravel配置CORS跨域访问
韩国代理服务器如何选?解析IP设置技巧与跨境访问优化指南
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
装修招标网站设计制作流程,装修招标流程?
如何快速生成凡客建站的专业级图册?
Bootstrap整体框架之JavaScript插件架构
Linux系统运维自动化项目教程_Ansible批量管理实战
Win11搜索不到蓝牙耳机怎么办 Win11蓝牙驱动更新修复【详解】
ChatGPT回答中断怎么办 引导AI继续输出完整内容的方法
html如何与html链接_实现多个HTML页面互相链接【互相】
php结合redis实现高并发下的抢购、秒杀功能的实例
如何在万网主机上快速搭建网站?
通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】
如何快速生成橙子建站落地页链接?
标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析
高防服务器租用指南:配置选择与快速部署攻略
INTERNET浏览器怎样恢复关闭标签页_INTERNET浏览器标签恢复快捷键与方法【指南】
Laravel如何使用Blade模板引擎?(完整语法和示例)
如何用VPS主机快速搭建个人网站?
Laravel storage目录权限问题_Laravel文件写入权限设置
如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)
Laravel如何生成PDF或Excel文件_Laravel文档导出工具与使用教程
如何在沈阳梯子盘古建站优化SEO排名与功能模块?
Laravel如何实现用户角色和权限系统_Laravel角色权限管理机制
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
详解Huffman编码算法之Java实现
Laravel怎么自定义错误页面_Laravel修改404和500页面模板
javascript中对象的定义、使用以及对象和原型链操作小结
Win11应用商店下载慢怎么办 Win11更改DNS提速下载【修复】
php读取心率传感器数据怎么弄_php获取max30100的心率值【指南】
电商网站制作价格怎么算,网上拍卖流程以及规则?
5种Android数据存储方式汇总
合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍?
Laravel如何发送邮件_Laravel Mailables构建与发送邮件的简明教程
百度浏览器网页无法复制文字怎么办 百度浏览器复制修复
手机怎么制作网站教程步骤,手机怎么做自己的网页链接?
如何在企业微信快速生成手机电脑官网?
EditPlus中的正则表达式 实战(4)
JavaScript中如何操作剪贴板_ClipboardAPI怎么用
Laravel N+1查询问题如何解决_Eloquent预加载(Eager Loading)优化数据库查询
如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环
如何在腾讯云免费申请建站?
家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?
西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?

