java表达式由什么组成_必知必会之Lambda表达式
Java是一门强大的面向对象的语言,除了8种基本的数据类型,其他一切皆为对象。因此,在Java中定义函数或方法都离不开对象,也就意味着很难直接将方法或函数像参数一样传递,而Java8中的Lambda表达式解决了这个问题。
一、为什么需要Lambda?
简单的来说,引入Lambda就是为了简化代码,允许把函数作为一个方法的参数传递进方法中。
1.1 真的简化了?
示例:如果想把某个接口的实现类作为参数传递给一个方法会怎么做?
Java8以前
public static void general() {
// 用匿名内部类的方式来创建线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("公众号:风尘博客!");
}
}).run();
}
Lambda 写法
public static void lambda() {
// 使用Lambda来创建线程
new Thread(() -> System.out.println("公众号:风尘博客!")).run();
}
1.2 Lambda表达式是什么?
Java中,将方法作为参数进行传递的方式被称为Lambda表达式。
1.3 Lambda 表达式语法结构
Lambda其实是一个箭头函数,也可称为匿名函数:->
箭头操作符将Lambda表达式分成了两部分:
左侧:Lambda表达式的参数列表(接口中抽象方法的参数列表)
右侧:Lambda表达式中所需执行的功能(Lambda体,对抽象方法的实现)
1.4 语法格式
无参,无返回值,Lambda 体只需一条语句。
public static void noParam() {
Runnable r1 = () -> System.out.println("noParam Test!");
r1.run();
}
Lambda 需要一个参数,参数的小括号可以省略。
public static void oneParam() {
// Consumer con = (s) -> System.out.println(s);
// 参数的小括号可以省略。
Consumer con = s -> System.out.println(s);
con.accept("oneParam Test!");
}
Lambda 需要多个参数,并且有返回值。
public static void params() {
Comparator com = (x, y) -> {
System.out.println("函数式接口");
// 比较x/y的大小
return Integer.compare(x, y);
};
System.out.println(com.compare(1, 2));
}
当 Lambda 体只有一条语句时,return 与大括号可以省略。
public static void one() {
Comparator com = (x, y) -> Integer.compare(x, y);
System.out.println(com.compare(1, 2));
}
上面几条示例好像有一个共性:参数列表的数据类型都没写,这是为什么呢?
1.5 类型推断
Lambda 表达式中的参数类型都是由编译器推断得出的。
public static void typeInference() {
//Integer 类型可以省略
Comparator com = (Integer x,Integer y) -> {
System.out.println("函数式接口");
return Integer.compare(x, y);
};
// 类型推断
BinaryOperator addImplicit = (x, y) -> x + y;
}
Lambda 表达式中无需指定类型,程序依然可 以编译,这是因为 javac根据程序的上下文,在后台 推断出了参数的类型。Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。
1.6 小节
Lambda表达式使得Java拥有了函数式编程的能力,但在Java中Lambda表达式是对象,它必须依附于一类特别的对象类型——函数式接口(functional interface)。
二、函数式接口
函数接口是只有一个抽象方法的接口,用作 Lambda 表达式的类型。使用@FunctionalInterface注解修饰的类,编译器会检测该类是否只有一个抽象方法或接口,否则,会报错。可以有多个默认方法,静态方法。
JDK8在 java.util.function 中定义了几个标准的函数式接口,供我们使用。
2.1 Java 内置四大核心函数式接口
函数式接口
参数类型
返回类型
用途
Consumer
T
void
对类型为T的对象应用操作,包含方法:void accept(T t)
Supplier
无
T
返回类型为T的对象,包 含方法:T get();
Function
T
R
对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t);
Predicate
T
boolean
确定类型为T的对象是否满足某约束,并返回 boolean 值。包含方法 boolean test(T t);
消费型接口
void accept(T t);
consumerDemo(3, s -> System.out.println(s * 3));
public static void consumerDemo(Integer value, Consumer consumer) {
consumer.accept(value);
}
供给型接口
T get();
// 生成10个以内的随机书
List numList = supplierDemo(10, () -> (int)(100 * Math.random()));
System.out.println(numList);
public static List supplierDemo(int num, Supplier supplier) {
List list = new ArrayList<>();
for (int i = 0; i < num; i++) {
Integer n = supplier.get();
list.add(n);
}
return list;
}
函数型接口
R apply(T t);
// 处理字符串
String str1 = functionDemo("Hello!风尘博客", s -> s.substring(6));
System.out.println(str1);
String str2 = functionDemo("vanDusty", s -> s.toUpperCase());
System.out.println(str2);
public static String functionDemo(String str, Function function) {
return function.apply(str);
}
断言型接口
boolean test(T t);
// 将满足条件的字符串放入集合
List list = Arrays.asList("hello", "van", "function", "predicate");
List newList = predicateDemo(list, s -> s.length() > 5);
System.out.println(newList);
public static List predicateDemo(List list, Predicate predicate) {
List newList = new ArrayList<>();
for (String s : list) {
if (predicate.test(s)) {
newList.add(s);
}
}
return newList;
}
2.2 自定义函数式接口
我们可以在任意函数式接口上使用 @FunctionalInterface 注解, 这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。
// 字符串转大写
String newStr = selfFunctionalInterface((str) -> str.toUpperCase(), "abc");
System.out.println(newStr);
public static String selfFunctionalInterface(SelfFunctionalInterface selfFunctionalInterface, String str) {
return selfFunctionalInterface.getValue(str);
}
三、方法引用和构造器引用
3.1 方法引用
方法引用是指通过方法的名字来指向一个方法。
3.1.1 方法引用使用的前提条件是什么呢?
方法引用所引用的方法的参数列表必须要和函数式接口中抽象方法的参数列表相同(完全一致);
方法引用所引用的方法的的返回值必须要和函数式接口中抽象方法的返回值相同(完全一致)。
3.1.2 方法引用三种格式
实例对象名::实例方法名
private static void instanceMethod() {
UserDomain user = new UserDomain(1L, "Van");
Supplier sup = () -> user.getUserName();
System.out.println(sup.get());
// 等同于
Supplier supplier = user::getUserName;
System.out.println(supplier.get());
}
类名::静态方法名
private static void staticMethod() {
Comparator com = (x, y) -> Integer.compare(x, y);
System.out.println(com.compare(3,9));
// 等同于
Comparator com2 = Integer::compare;
System.out.println(com2.compare(3,9));
}
类名::实例方法名
private static void instanceMethodObject() {
UserDomain user = new UserDomain(1L, "Van");
Function fun = (e) -> e.getUserName();
System.out.println(fun.apply(user));
// 等同于
Function fun2 = UserDomain::getUserName;
System.out.println(fun2.apply(user));
}
3.2 构造器引用
前提:构造器参数列表要与接口中抽象方法的参数列表一致!
语法格式:类名 :: new
构造器引用
private static void object() {
// UserDomain 中必须有一个 UserDomain(String userName) 的构造器,下同
Function fun = (n) -> new UserDomain(n);
fun.apply("Van");
System.out.println("===等价于===");
Function function = UserDomain::new;
function.apply("Van");
// 带两个参数的构造器引用就要用BiFunction,多个参数的话,还可以自定义一个这样的函数式接口
BiConsumer biConsumer = UserDomain :: new;
biConsumer.accept(1L,"Van");
}
数组引用
private static void array() {
//传统Lambda实现
Function function = (i) -> new int[i];
int[] apply = function.apply(10);
System.out.println(apply.length);
//数组类型引用实现
function = int[] ::new;
apply = function.apply(100);
System.out.println(apply.length);
}
四、 总结
Lambda表达式是Java对于函数式编程的温和转变,面向对象编程和函数式编程不是互相对立的,结合使用能够更加有效地帮助我们管理程序的复杂性。
技术交流
java表达式由什么组成_必知必会之Lambda表达式相关推荐
- java的标量和聚合量_第5节:Java基础 - 必知必会(下)
第5节:Java基础 - 必知必会(下) 本小节是Java基础篇章的第三小节,主要讲述Java中的Exception与Error,JIT编译器以及值传递与引用传递的知识点. 一.Java中的Excep ...
- SpringBoot入门到精通_第6篇 _必知必会
接上一篇:SpringBoot入门到精通_第5篇 _SpringBoot Actuator监控 https://blog.csdn.net/weixin_40816738/article/detail ...
- mysql日期维表sql文件_《MySQL必知必会》笔记(SQL练习+建表语句)
站在巨人的肩上 Standing On Shoulders Of Giants 部分转自:https://www.jianshu.com/p/294502893128 https://blog.csd ...
- Java架构师必知必会,带走不谢
可以说,Java是现阶段中国互联网公司中,覆盖度最广的研发语言,掌握了Java技术体系,不管在成熟的大公司,快速发展的公司,还是创业阶段的公司,都能有立足之地. 成为Java架构师,需要掌握哪些技能呢 ...
- c2064 项不会计算为接受0个参数的函数_【JS必知必会】高阶函数详解与实战
本文涵盖 前言 高级函数概念 函数作为参数的高阶函数 map filter reduce sort详解与实战 函数作为返回值的高阶函数 isType函数与add求和函数 如何自己创建高阶函数 前言 一 ...
- SpringBoot入门到精通_第7篇 _必知必会总结
接上一篇:SpringBoot入门到精通_第6篇 _必知必会
- java面试必知必会
java面试必知必会 面向对象 成员变量成员方法 Integer相关 double 和 Double相关 多态,向上转型 hashcode.==.equals比较 java中子类继承父类时是否继承构造 ...
- 《SQL必知必会》第六课 用通配符进行过滤 使用LIKE操作符,%、[]、_通配符进行通配搜索
第六课 用通配符进行过滤 使用LIKE操作符,%.[]._通配符进行通配搜索 #前面使用的所有操作符过滤中使用的值都是已知的 #利用通配符可以创建比较特定数据的搜索模式 #通配符:用来匹配值的一部分的 ...
- 读mysql必知必会有感_读《MySql必知必会》笔记
MySql必知必会 2017-12-21 意义:记录个人不注意的,或不明确的,或不知道的细节方法技巧,此书250页 登陆: mysql -u root-p -h myserver -P 9999 SH ...
- 必知必会系列-JAVA虚拟机原理
系列文章 必知必会系列-Spring技术原理 必知必会系列-JAVA虚拟机原理 必知必会系列-Redis技术原理 引言 随着技术的不断演进,在不同时间阶段都会有不同的技术产物,那么如何快速的学习和掌握 ...
最新文章
- SpringBatch 写文件JSON(JsonFileItemWriter)用法(十二)
- forms身份验证 不跳转_Django用户身份验证实战
- 编译安装日志分析平台 elk + beats(个人感觉不错1)
- 2021年金三银四春招实习回顾
- java.util.Date与 java.sql.Date两个包下Date的区别与联系
- PyTorch官方权威教程书来了,LeCun力荐!意外的通俗易懂
- 【PyTorch v1.1.0文档研习】60分钟快速上手
- extract提取返回结果中的内容_httprunner如何提取数据串联上下游接口
- 自定义 Web 服务器控件
- phpmyadmin的安装和使用
- 学习红黑树过程中的个人总结
- 【LeetCode】【字符串】题号:*165. 比较版本号
- TRACKER : 错误 TRK0005: 未能找到: “CL.exe”。系统找不到指定的文件。 无法打开源文件iosteam
- java安卓开发——1.新项目搭建
- c语言方框透视原理,FPS游戏的方框透视+自瞄原理
- 日版iphone5 SB 配合REBELiOS卡贴破解电信3G步骤
- 为 Kodi 自制遥控器
- 高维数据软子空间聚类FSC
- win10安装mongoDB
- 多重背包问题——庆功会
热门文章
- 汇编中断知识之INT 1CH
- 一个信道的数据传输速率为4kb/s,单向传播时延为30ms,如果使停止-等待协议的信道最大利用率达到80%,那么要求的数据帧长度至少为( )
- 《算法竞赛入门经典》 例题3-5 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
- 【机器视觉】 comment算子
- 【Linux】一步一步学Linux——wget命令(192)
- 如何制作linux系统硬盘,教你制作Linux操作系统的Boot/Root盘
- java异常处理试题答案_JAVA异常处理试题及答案
- python 三元运算符求abc_python三元运算符实现方法
- 登录mysql报错2059_navicat连接mysql报错2059的解决方法
- 隐藏水滴屏的软件_突破屏下摄像头技术,vivo APEX 2020,开启全面屏手机黑科技!...