详解Java中的Lambda表达式
作者:rickiyang 发布时间:2021-08-17 00:06:00
Java 目前已经出到13的版本,但是国内大部分公司应该都停留在 Java 8 的版本(不敢承担升级带来的风险)。在Java8中给我们带来了 Lambda表达式和Stream流式操作,提供了函数式编程和简化批处理操作。可能大家日常使用很多,但是很少去关注Lambda 和 Stream实现。本篇就带着大家一起关注这两块知识,搬好小板凳我们一起看电视。
什么是Lambda
简单来说,编程中提到的 lambda 表达式,通常是指需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。
一般我们使用变量来进行赋值操作:
但是在 Java8 之前是没有提供将一个方法赋值给一个变量的操作:
在 JavaScript 中有 闭包的概念,所以 Java不甘落后,也去学习了人家,搞出了匿名函数的概念。
在Java 8里面,所有的Lambda的类型都是一个接口,而Lambda表达式本身,也就是”那段代码“,需要是这个接口的实现。这是我认为理解Lambda的一个关键所在,简而言之就是,Lambda表达式本身就是一个接口的实现。
基本语法:
(parameters) -> { expression or statements }
示例:
// 无参数, 返回1+2的结果
() -> 1+2;
// 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x;
// 接收2个参数(数字),返回表达式运算的结果
(x, y) -> x + y;
// 多个语句要用大括号包裹, 并且返回值要用return指明
(x, y) -> {
int result = x + y;
System.out.print(result);
return result;
};
Lambda表达式有如下约定:
一个 Lambda 表达式可以有零个或多个参数;
参数的类型既可以明确声明,也可以根据上下文来推断。例如:(int a)与(a)效果相同;
所有参数需包含在圆括号内,参数之间用逗号相隔。例如:(a, b) 或 (int a, int b) 或 (String a, int b, float c);
空圆括号代表参数集为空。例如:() -> 42;
当只有一个参数,且其类型可推导时,圆括号()可省略。例如:a -> return a*a;
Lambda 表达式的主体可包含零条或多条语句;
如果 Lambda 表达式的主体只有一条语句,花括号{}可省略。匿名函数的返回类型与该主体表达式一致;
如果 Lambda 表达式的主体包含一条以上语句,则表达式必须包含在花括号{}中(形成代码块)。匿名函数的返回类型与代码块的返回类型一致,若没有返回则为空。
@FunctionalInterface 是 Java 8 新加入的一种接口,用于指明该接口类型声明是根据 Java 语言规范定义的函数式接口。Java 8 还声明了一些 Lambda 表达式可以使用的函数式接口,当你注释的接口不是有效的函数式接口时,可以使用 @FunctionalInterface 解决编译层面的错误。
根据定义,函数式接口只能有一个抽象方法,如果你尝试添加第二个抽象方法,将抛出编译时错误。例如:
@FunctionalInterface
public interface DoSomethingInterface {
void doSomeThing();
void doSomeThing1();
}
举一个简单使用的例子,首先定义一个接口:
@FunctionalInterface
public interface DoSomethingInterface<T> {
String doSomeThing(T t);
}
这个接口里面只能有一个函数,接口里是返回值为String类型的方法,那么下面使用它的时候就需要有返回值:
class MainTest{
public static void main(String[] args) {
DoSomethingInterface<String> t = str -> {
return str;
};
String print = t.doSomeThing("print");
System.out.println(print);
}
}
t就相当于是接口的具体实现,那么使用 t.doSomeThing("print")就会去调用 t 的匿名函数执行。从这段代码看,如果我们有一个抽象类的具体实现逻辑相对简单不用大段代码的时候,可以使用 Lambda 表达式去实现具体的逻辑,这样就不用new 多个类。
Java 8 内置4大核心函数式接口
大家日常使用的List,Map,肯定大量使用了Stream流式处理,在流式处理中大量使用了Lambda,比如List的foreach方法就使用了Lambda表达式。Java8中抽象出来4类基本的函数式接口,日常开发中我们其实也是可以使用的。
函数式接口 | 参数类型 | 返回类型 | 用途 |
Consumer | T | Void | void accept(T t) :将T 类型的参数应用于该方法 |
Supplier | T | T | T get():返回类型为T 的对象 |
Function<T,R> | T | R | R apply(T t):输出T类型的参数返回R类型的结果 |
Predicate | T | Boolean | boolean test(T t): 确定类型为T 的参数是否满足test逻辑 |
以上4种类型是Java默认提供的Lambda类,开箱即用。
Consumer使用:
public void test(){
save(user, t->{ saveUser(t); });
}
public void save(User user, Consumer<User> consumer){
consumer.accept(user);
}
Supplier使用:
public void test(){
Config config = getConfig(t -> {
return getAllConfig(t);
});
}
public Config getConfig(Supplier<Config> supplier) {
return supplier.get();
}
Function使用:
public void test(){
User user = getUser(t -> { return getUserByName(t); });
}
public User getUser(Function<String, User> function) {
return function.apply(t);
}
Predicate使用:
public void test(){
boolean b = checkStatus(user, t -> {
return checkUserExist(t);
});
}
public boolean checkStatus(User user, Predicate<User> predicate) {
return predicate.test(user);
}
以上关于Lambda就介绍到这里,大家应该明白了它是干啥的了吧。闭包是不是也没有这么难懂呢!联想到List的foreach使用,大家有没有冲动想自己实现一个Lambda在日常开发中炫一把(如果别人看不懂,会打你的)。
来源:https://www.cnblogs.com/rickiyang/p/12052237.html


猜你喜欢
- 本文实例讲述了Android编程使WebView支持HTML5 Video全屏播放的解决方法。分享给大家供大家参考,具体如下:1)需要在An
- @RequestBody部分属性丢失问题描述JavaBean实现public class VerifyNewFriendApplyReq i
- 枚举的基本用法回顾以下是一个常见的 C# 枚举(enum)的示例:enum Weekday{
- 最近一段时间,大家在用 Spring Security OAuth2 时可能发现有很多类过期了。大家在选择 OAuth2 依赖的时候,可能也
- 前两天,谷歌发布了Android Studio 1.0的正式版,也有更多的人开始迁移到Android Studio进行开发。然而,网上很多的
- 概述为文档添加必要的批注可以给文档使用者提供重要的提示信息,下面的示例中,将介绍通过C#编程语言来给Excel表格中的指定单元格内容添加批注
- 前言近期一直在忙项目,我也是打工仔。不多说,我们开始玩一玩seata。什么都不说,我们按照惯例,先上一个图(图里不规范的使用请忽略):简单一
- 使用YZMHelper帮助类即可using System;using System.Web;using System.Drawing;usi
- 一、枚举的概念:C# 枚举(Enum), 枚举类型是用于声明一组命名的常数的基本数据类型(值类型);二、枚举的定义:声明enum变量:enu
- 本例子演示如何添加一个简单的单页导航,在此基础上,再演示如何在第2个页面中显示第1个页面中拨打过的所有电话号码。(1)通过该例子理解Andr
- 一、前言最近在看android fragment与Activity进行数据传递的部分,看到了接口回调的内容,今天来总结一下。二、回调的含义和
- 一、 lib文件的简介.lib是一种文件后缀,是Windows操作系统的库文件,有静态lib和动态lib之分:1)、静态lib文件
- ApplicationContextAware 通过它Spring容器会自动把上下文环境对象调用ApplicationContex
- #include<iostream>#include<assert.h>using namespace std;st
- 本示例演示如何通过设置Intent对象的标记,来改变当前任务堆栈中既存的Activity的顺序。1. Intent对象的Activity启动
- 在文章中,我们将对输入到机器学习模型中的数据集进行预处理。这里我们将对一个硬币数据集进行预处理,以便以后在监督学习模型中进行训练。在机器学习
- Seata介绍Seata:Simple Extensible Autonomous Transaction Architecture,简易可
- Mybatis防止sql注入原理SQL 注入是一种代码注入技术,用于攻击数据驱动的应用,恶意的SQL 语句 * 入到执行的实体字段中(例如,为
- C#可以直接引用C++的DLL和转换JAVA写好的程序。最近由于工作原因接触这方面比较多,根据实际需求,我们通过一个具体例子把一个JAVA方
- 在页面提交到tomcat乱码 解决方法是在tomcat/conf/server.xml中进行配置以tomcat6.0.32为例,需将以下代码