【学习笔记】Java函数式编程01-Lambda表达式

文章目录

  • 一、概述
    • 1.1 为什么学习函数式编程
    • 1.2 函数式编程思想
      • 1.2.1 概念
      • 1.2.2 优点
  • 二、Lambda表达式
    • 2.1 概述
    • 2.2 核心原则
    • 2.3 基本格式
      • 2.3.0 小结
      • 2.3.1 案例一:匿名内部类写法
        • :star2:**什么情况可以进行Lambda进行简化?**
      • 2.3.2 案例二:IntBinaryOperator(计算
        • :star:知识点延伸:IDEA的快捷操作
      • 2.3.3 案例三: IntPredicate(断言
      • 2.3.4 案例四:Function (方法泛型
        • :star: 在学习初期,先不要求手写接口,先学会如何[调用和使用]即可
      • 2.3.5 案例五 IntConsumer(消费者
    • 2.4 省略规则
      • 2.4.1 参数类型可以省略
      • 2.4.2 方法体只有一句代码时的省略规则
      • 2.4.3 方法只有一个参数时,小括号可以省略
      • 2.4.4 以上规则记不住可以不记

一、概述

1.1 为什么学习函数式编程

  • 看懂代码
  • 提高处理大数据量集合的效率
  • 代码可读性提升
    • 消灭嵌套地狱(反复的嵌套for …if …for …if …导致可读性下降

1.2 函数式编程思想

1.2.1 概念

类似数学中的函数,主要关注对数据进行的操作

  • 面向对象思想:关注什么对象做了什么事情。
  • 函数式编程:并不关心对象和具体的参数类型,而是关注对数据进行了什么操作

1.2.2 优点

  • 代码简洁(开发快速
  • 接近自然语言,易于理解(需要学习成本
  • 易于并发编程并行流/对大数据的处理效率很高

二、Lambda表达式

2.1 概述

Lambda表达式可以理解为JDK8新增了一个语法糖。

  • 对某一些匿名内部类的写法进行简化。
  • 是函数式编程的重要体现
  • 让程序员不用关注对象,而关注对数据的操作

关于语法糖:语法糖(Syntactic sugar),也译为糖衣语法

[外链图片转存中…(img-ultqjqy9-1703122023748)]

计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。

通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。

2.2 核心原则

可推导、可省略

  • 如果一个参数的类型可以被推导出来,则可以省略参数类型
  • 如果方法名可以被推导出来,则可以省略方法名

2.3 基本格式

(参数列表) —> {代码}

2.3.0 小结

要理解函数式编程,一开始不要想着一次性写出最简单的写法,应该从匿名内部类的写法开始逐步优化,循序渐进。

2.3.1 案例一:匿名内部类写法

创建一个Runnable接口的实现类为构造参数的线程类。

new Thread() // 线程的构造函数可以传入一个Runnable接口的实现类
  • 实现类可以用匿名内部类的形式书写,如下
new Thread(new Runnable() {@Overridepublic void run(){System.out.println("异步执行的方法")}
}).start();

也可以使用Lambda表达式进行简化优化,延伸一个问题,

🌟什么情况可以进行Lambda进行简化?
  • 这个匿名内部类是一个接口的实现,并且只有一个抽象方法需要重写
  • 即:接口+单方法

函数式写法遵循的核心原则之一是**“可省略”**,那么方法的5要素有哪些部分是可以省略的?

  • 作用域
  • 返回值
  • 方法名
  • 参数列表
  • 方法体

所以由此也可推证:函数式关注的重点是“数据+对数据的操作

经过简化后的代码:

// (略去了方法名、作用域、返回值)
new Thread(() -> {System.out.println("线程运行");
}).start();

2.3.2 案例二:IntBinaryOperator(计算

先定义一个方法如下,练习如何调用该方法

public static int calculate(IntBinaryOperator operator){int a = 10;int b = 20;return operator.applyAsInt(a , b);
}

查看源码可以发现,IntBinaryOperator是一个单方法的接口,符合函数式编程的写法

public interface IntBinaryOperator {int applyAsInt(int left, int right);
}

为了便于初学,我们选择一开始先写匿名内部类,然后再进行简化,如下

public static void main(String[] args) {int calculate = calculate(new IntBinaryOperator() {@Overridepublic int applyAsInt(int left, int right) {return left + right;}});System.out.println("没有简写的计算结果:"+calculate);int calculate1 = calculate((int left, int right) -> {return left + right;});System.out.println("简写后的计算结果:"+calculate1);
}
  • 不难发现,这个接口的作用就是让程序员自定义int left, int right的计算逻辑
⭐️知识点延伸:IDEA的快捷操作

使用alt+enter快捷键可以在匿名内部类和lambda表达式之间快速切换

[外链图片转存中…(img-2AAOswwC-1703122023750)]

[外链图片转存中…(img-sT7c6k9G-1703122023750)]

2.3.3 案例三: IntPredicate(断言

定义下面的方法,练习如何调用

public static void predicate(IntPredicate intPredicate) {int[] arr = {0, 2, 3, 4, 5, 6, 7, 11, 23, 55, 120, 560, 777, 8888, 9999};for (int i : arr) {if (intPredicate.test(i)) {System.out.println(i + "\t断言为true");}}
}

查看IntPredicate源码,第一眼会发现这个接口有多个方法,但是仔细看就会发现,其实只有一个抽象方法boolean test(int value),所以符合lambda简化的要求——只有一个抽象方法的接口

public interface IntPredicate {boolean test(int value);// 。。。。 其他方法
}

练习代码如下:

public class Main03 {public static void main(String[] args) {// 匿名内部类写法predicate(new IntPredicate() {@Overridepublic boolean test(int value) {return value%2 == 0;}});// lambda简化写法predicate((int value) -> {return value%2 == 0;});}public static void predicate(IntPredicate intPredicate) {int[] arr = {0, 2, 3, 4, 5, 6, 7, 11, 23, 55, 120, 560, 777, 8888, 9999};for (int i : arr) {if (intPredicate.test(i)) {System.out.println(i + "\t断言为true");}}}
}

2.3.4 案例四:Function (方法泛型

定义下面这个方法,练习如何调用

public static <R> R typeConvert(<String, R> function) {String str = "666";return function.apply(str);
}

查看Function<T, R>源码,可以看到方法利用泛型参数指定了apply方法的传入的参数类型和返回的参数类型

和案例三源码一样,其他的默认方法先不看,关注其中一个抽象方法即可

public interface Function<T, R> {R apply(T t);// 。。。。其他方法
}

在案例四里,已经将泛型T定义为String,即默认Funtion传入的参数为String,而返回的类型可以让方法的调用者来定义。

练习代码

public class Main04 {public static <R> R typeConvert(Function<String, R> function) {String str = "666";return function.apply(str);}public static void main(String[] args) {// 匿名类写法Integer integer = typeConvert(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return Integer.valueOf(s);}});System.out.println("匿名类写法结果:" + integer);// Lambda简写优化写法Integer integer1 = typeConvert((String s) -> {return Integer.valueOf(s);});System.out.println("lambda写法结果:" + integer1);}
}
  • 这个方法将typeConvert作用为将string转换为integer的一个方法
⭐️ 在学习初期,先不要求手写接口,先学会如何[调用和使用]即可

可以从java提供的一些方法入手,循序渐进的进行联系

2.3.5 案例五 IntConsumer(消费者

IntConsumer也是java自带的函数接口,是一个没有返回值的消费方法,不赘述,直接上代码。

方法代码

public static void accept(IntConsumer consumer){int[] arr = {0, 2, 3, 4, 5, 6, 7, 11, 23, 55, 120, 560, 777, 8888, 9999};for (int i : arr) {consumer.accept(i);}
}

使用代码

public static void main(String[] args) {accept(new IntConsumer() {@Overridepublic void accept(int value) {System.out.println("消费int的数值:"+value);}});accept((int value) -> {System.out.println("消费int的数值:"+value);});
}

2.4 省略规则

  • 参数类型可以省略
  • 方法体只有一句代码时,大括号return和唯一一句代码的分号可以省略
  • 方法只有一个参数时,小括号可以省略

以上规则记不住,也可以不省略(废话

这里的规则也是遵循“可推导、可省略”的大原则,不建议死记硬背

2.4.1 参数类型可以省略

首先这个规则符合“参数类型可推导”的大原则,实际上,当代码能确认这个lambda表达式所指代的抽象方法时,参数类型也就随之确认了。

比如案例二的写法就可以再省略为:

int calculate1 = calculate((int left, int right) -> {return left + right;
});// ####简化参数类型####
int calculate2 = calculate((a, b) -> {return a + b;
});

2.4.2 方法体只有一句代码时的省略规则

方法体只有一句代码时,可以省略:

  • 大括号可以省略
  • return可以省略
  • 分号可以省略

注意:以上三个必须一起省略,否则会编译报错。.

还是以案例2为例子,进行进一步优化

// ####简化参数类型####
int calculate2 = calculate((a, b) -> {return a + b;
});
// ####只有唯一一句代码时####
int calculate3 = calculate((a, b) ->  a + b );

[外链图片转存中…(img-1YuQkeTB-1703122023751)]

2.4.3 方法只有一个参数时,小括号可以省略

很好理解,也是符合“可推导、可省略”的大原则,当只有一个参数时,参数类型肯定是确定的,即使略去小括号也不会产生歧义。

以案例三基础上进行简化

// lambda简化写法
predicate((int value) -> {return value%2 == 0;
});
// ###方法只有一个参数时,小括号可以省略###
predicate(value -> value%2 ==0);

[外链图片转存中…(img-i47xrR8Y-1703122023753)]

2.4.4 以上规则记不住可以不记

使用IDEA的快捷键

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习目标检测(2)yolov3设计思想

YOLOv3基础 YOLOv3算法基本思想可以分成两部分&#xff1a; 按一定规则在图片上产生一系列的候选区域&#xff0c;然后根据这些候选区域与图片上物体真实框之间的位置关系对候选区域进行标注。跟真实框足够接近的那些候选区域会被标注为正样本&#xff0c;同时将真实框的位置…

Qt获取屏幕DPI缩放比

获取屏幕缩放比 网上很多代码是用 logicalDotsPerInch 除以 96 来获取屏幕缩放比&#xff1a; // Windows 除以 96&#xff0c;macOS 除以 72 qreal factor window->screen()->logicalDotsPerInch() / 96.0; 当使能了缩放适配后&#xff0c;logicalDotsPerInch 值就不…

Sentinel 流量治理组件教程

前言 官网首页&#xff1a;home | Sentinel (sentinelguard.io) 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形…

macOS 开发 - MASShortcut

文章目录 关于 MASShortcut项目结构 快速使用源码学习检测是否有热键冲突处理 Event macOS 开发交流 秋秋群&#xff1a;644096295&#xff0c;V : ez-code 关于 MASShortcut MASShortcut 是一款快捷键管理工具&#xff0c;替代和兼容 ShortcutRecorder github : https://git…

Pytorch常用的函数(五)np.meshgrid()和torch.meshgrid()函数解析

Pytorch常用的函数(五)np.meshgrid()和torch.meshgrid()函数解析 我们知道torch.meshgrid()函数的功能是生成网格&#xff0c;可以用于生成坐标&#xff1b; 在numpy中也有一样的函数np.meshgrid()&#xff0c;但是用法不太一样&#xff0c;我们直接上代码进行解释。 1、两者…

最新消息丨OpenAI灰度测试GPT-4.5-turbo,快看看,你的版本是最新的吗?

刚刚&#xff0c;有朋友发来消息说&#xff1a;OpenAI 正在灰度测试它的最新模型——GPT-4.5-turbo。 于是&#xff0c;赶紧测了一下&#xff0c;发现果然如此。 相比于之前的 GPT-4-turbo&#xff0c;GPT-4.5-turbo 增强了6大能力。 分别是&#xff1a; √效率和性能&#x…

Redis哨兵源码分析

在Redis server启动过程中&#xff0c;实现了实例化和初始化 1、哨兵实例化过程&#xff0c;采用redis sentinel指令实例化还是redis server下的参数实例化--sentinel。 // 检查服务器是否以 Sentinel 模式启动 server.sentinel_mode checkForSentinelMode(argc,argv);/* Re…

分子生成工具 - ResGen 评测

ResGen 模型是浙江大学药学院侯廷军老师课题组2023年发表在nature machine intelligence期刊上文章Nature Machine Intelligence | Volume 5 | September 2023 | 1020–1030&#xff0c;题目为&#xff1a;《ResGen is a pocket-aware 3D molecular generation model based on …

java: -source 7 中不支持 lambda 表达式 (请使用 -source 8 或更高版本以启用 lambda 表达式)

目录 1、检查项目中 JDK 的设置&#xff1a; 2、检查模块中 JDK 的设置&#xff1a; 3、检查Idea 中的SDK设置 4、检查 IDEA 中 JDK 的设置&#xff08;我出现的问题在这&#xff09;&#xff1a; 今天遇见了一个报错&#xff1a; 问题产生的原因是 JDK 版本太低&#xf…

从程序员到百万富翁,他的技能和智慧是关健

我要跟大家分享一个超级励志的故事&#xff01;&#x1f389;这个故事的主人公是一位普通的程序员&#xff0c;但他通过自己的努力和智慧&#xff0c;成功地实现了从平凡到非凡的飞跃&#xff0c;成为了一位百万富翁&#xff01;你们一定很好奇他是怎么做到的吧&#xff1f;别急…

【JAVA面试题】什么是深拷贝?什么是浅拷贝?

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; JAVA ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 一、解释 1. 深拷贝&#xff08;Deep Copy&#xff09;&#xff1a; 2. 浅拷贝&#xff08;Shallow Copy&#xff09;&#xff1…

企业级“RAS”的数据平台如何炼成?

从“看报表”到“数据分析结果直接投入运营”&#xff0c;数字化正在深入企业经营&#xff0c;数据系统正在成为核心生产系统。相应的&#xff0c;企业对“作业挂了”、“系统崩了”、“算不出来”的容忍度越来越低——只有足够稳定、可靠、专业的数据系统&#xff0c;才能及时…

原生微信小程序中使用-阿里字体图标-详解

步骤一 1、打开阿里巴巴矢量图标库 网址&#xff1a;iconfont-阿里巴巴矢量图标库 2、搜索字体图标&#xff0c;鼠标悬浮点击添加入库 3、按如下步骤添加到自己的项目 步骤二 进入微信开发者工具 1、创建 fonts文件夹 > iconfont.wxss 文件&#xff0c;将刚才的代码复制…

python脚本传参

sys.argvargparse 第一种&#xff1a;argparse 简单使用&#xff1a; import argparse # 创建一个参数解析实例 parser argparse.ArgumentParser(descriptionParameters) # 添加参数解析 parser.add_argument(--training_epoch, typeint, default3000) parser.add_argument(…

进程间通信---无名管道

无名管道和有名管道的区别&#xff1a; 无名管道只能用于父进程和子进程之间通信&#xff0c;而有名管道可以用于任意两个进程间通信 管道工作的原理&#xff1a; 切记&#xff1a;无名管道一旦创建完成后&#xff0c;操作无名管道等同于操作文件&#xff0c;无名管道的读端/写…

Codeforces Round 862 (Div. 2)

Problem - A - Codeforces AC代码: #include<bits/stdc.h> #define endl \n //#define int long long using namespace std; const int N1e310; int a[N]; int n; void solve() {cin>>n;int ans0;for(int i1;i<n;i) cin>>a[i],ans^a[i];if(n%21){for(in…

LeetCode——2415. 反转二叉树的奇数层

通过万岁&#xff01;&#xff01;&#xff01; 题目&#xff1a;给你一个完全二叉树&#xff0c;然后将其奇数层进行反转。思路&#xff1a;这个题他都说了是奇数层了&#xff0c;那基本就是层序遍历了。但是存在两个问题&#xff0c;一个是如何判断奇数层&#xff0c;另外一…

测试开发体系介绍——测试体系介绍-L2

目录&#xff1a; 被测系统架构与数据流分析 开源项目 LiteMall 系统架构&#xff1a;开源项目 Mall 的系统架构&#xff1a;如何快速了解一家公司的架构统一建模语言 UML推荐工具梳理业务流程&#xff1a;使用思维导图分析功能点:使用时序图分析数据流:使用活动图分析测试用例…

20-二分-值域二分-分割数组的最大值

这是二分法的第20篇算法&#xff0c;力扣链接。 给定一个非负整数数组 nums 和一个整数 k &#xff0c;你需要将这个数组分成 k 个非空的连续子数组。 设计一个算法使得这 k 个子数组各自和的最大值最小。 示例 1&#xff1a; 输入&#xff1a;nums [7,2,5,10,8], k 2 输出&a…

oracle数据库sqlplus登录卡顿

问题描述 新安装了一套oracle 11.2.0.1 版本的数据库服务器&#xff0c;出现了在服务器本地通过sqlplus / as sysdba登录的时候很快&#xff0c;但是通过监听登录的时候就非常的慢&#xff0c;卡顿&#xff0c;大概需要1分钟多的时间才能登进数据库。 之前安装了好几套oracle …