再来看看Java8的新特征——lambda表达式

什么是lambda表达式?
可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。
比如说new一个Thread的传统写法如下
Thread t = new Thread(new Runnable() {
public void run(){
System.out.println("Hello world");
}
});
那么利用lambda表达式的写法就是
Thread t = new Thread(() -> System.out.println("Hello world"));
->左边的就是参数列表,->右边的就是函数主体
函数式接口
为什么@FunctionalInterface注解修饰的类只能有一个抽象函数
查看Java8的源码,被@FunctionalInterface修饰的函数叫做函数式接口,例如Predicate,这些类往往只有一个抽象函数,那是因为“Lambda表达式理解为简洁地表示可传递的匿名函数”,直接使用的匿名函数的时候没有指定函数名称,所以,如果有两个及以上抽象函数的时候,虚拟机就不知道你要执行哪个方法了,如上例中Runnable的run()方法,我们参数列表部分只使用了(),并没有声明调用的函数名。
JDK自带的函数式接口都在java.util.function路径下,常用的有
public interface Predicate<T>{
boolean test (T t);
}
public interface Consumer<T> {
void accept(T t);
}
public interface Function<T, R> {
R apply(T t);
}
...
函数式接口使用示例
//源码部分
@FunctionalInterface
public interface Predicate<T>{
boolean test(T t);
}
//方法构建
public static <T> List<T> filter(List<T> list, Predicate<T> p) {
List<T> results = new ArrayList<>();
for(T s: list){
if(p.test(s)){
results.add(s);
}
}
return results;
}
//使用示例,通过filter方法,筛选出String不为空的数据
Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);
其他函数式接口使用示例
为什么lambda表达式使用局部变量必须是final的?
lambda表达式主体部分除了使用参数列表的数据,还可以使用lambda表达式外部的局部变量,但是这些局部变量只能声明一次,否则就会报错。
int portNumber = 1337;
//此时会报错,portNumber必须被final修饰
Runnable r = () -> System.out.println(portNumber);
portNumber = 31337;
因为lambda表达式主体可看作是匿名内部类,访问外部局部变量是需要final的。从线程的角度来说,就是局部变量是一个线程(假设叫线程A),lambda表达式主体是另外一个线程(线程B),当线程A结束的时候,线程B还要访问线程A的数据,肯定是不行的,所以线程B中的变量实质上不是指向线程A中的变量,而是拷贝了一份出来,所以必须保证拷贝出来的数据是不可以改变的。
方法引用
lambda表达式还有一个非常方便的地方,就是方法引用,可以通过类名::方法名的形式直接使用方法。
例如
//静态方法
Integer::parseInt
//对象的普通方法
String::length
//构造方法
Apple::new
复合lambda表达式的用法
lambda表达式还可以链式调用,同时拥有与或非(negate、and和or)的逻辑判断
//链式调用
inventory.sort(comparing(Apple::getWeight)
.reversed()
.thenComparing(Apple::getCountry));
//非
Predicate<Apple> notRedApple = redApple.negate();
//与
Predicate<Apple> redAndHeavyApple =
redApple.and(a -> a.getWeight() > 150);
//或
Predicate<Apple> redAndHeavyAppleOrGreen =
redApple.and(a -> a.getWeight() > 150)
.or(a -> "green".equals(a.getColor()));
函数复合
Function函数接口提供了两个方法对数据做连续操作,andThen和compose方法。
Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.compose(g);
int result = h.apply(1);
//输出3 ==> )(1*2)+1
andThen方法相当于先执行f函数,再执行g函数。
Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.andThen(g);
int result = h.apply(1);
//输出4 ==> (1+1)*2
compose方法相当于先执行g函数,再执行f函数。
接下来
接下来会梳理流的相关知识点、和其他(注入Optionnal、新的时间工具、默认方法等知识)。
再来看看Java8的新特征——lambda表达式的更多相关文章
- Java8新特性-Lambda表达式是什么?
目录 前言 匿名内部类 函数式接口 和 Lambda表达式语法 实现函数式接口并使用Lambda表达式: 所以Lambda表达式是什么? 实战应用 总结 前言 Java8新特性-Lambda表达式,好 ...
- 【Java8新特性】你知道Java8为什么要引入Lambda表达式吗?
写在前面 这是一道真实的面试题,一个读者朋友出去面试,面试官竟然问他这样一个问题:你说说Java8中为什么引入Lambda表达式?引入Lambda表达式后有哪些好处呢?还好这个朋友对Java8早有准备 ...
- 乐字节-Java8新特性-Lambda表达式
上一篇文章我们了解了Java8新特性-接口默认方法,接下来我们聊一聊Java8新特性之Lambda表达式. Lambda表达式(也称为闭包),它允许我们将函数当成参数传递给某个方法,或者把代码本身当作 ...
- Java 8 新特性 - Lambda表达式
Lambda表达式 vs 匿名类既然lambda表达式即将正式取代Java代码中的匿名内部类,那么有必要对二者做一个比较分析.一个关键的不同点就是关键字 this.匿名类的 this 关键字指向匿名类 ...
- C#10新特性-lambda 表达式和方法组的改进
C# 10 中对Lambda的语法和类型进行了多项改进: 1. Lambda自然类型 Lambda 表达式现在有时具有"自然"类型. 这意味着编译器通常可以推断出 lambda 表 ...
- java8新特性——Lambda表达式
上文中简单介绍了一下java8得一些新特性,与优点,也是为本次学习java8新特性制定一个学习的方向,后面几篇会根据上文中得新特性一一展开学习.本文就从java8新特性中比较重要的Lambda表达式开 ...
- java8新特性-lambda表达式和stream API的简单使用
一.为什么使用lambda Lambda 是一个 匿名函数,我们可以把 Lambda表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...
- Java8新特性 - Lambda表达式 - 基本知识
A lambda expression is an unnamed block of code (or an unnamed function) with a list of formal param ...
- Java8 新特性lambda表达式(一)初始
本篇参考Richard Warburton的 java8 Lambdas :Functional Programming for the Masses 学习lambda表达式之前,需要知道什么是函数式 ...
随机推荐
- Pycharm2020最新激活码|永久激活(附最新激活码和插件)
最近很多人的Pycharm激活时间又过期了,后台很多人索要激活码,我就再把激活的方法汇和工具再梳理一次给大家. 最主要有两种激活方式(两种方式需要的激活码不同): 一.激活码激活: 一般一年多需要激活 ...
- 使用 this 关键字定义方法和属性
1.方法和属性的定义 属性是类中声明的变量,与其他地方变量的声明基本相同,只是属性必须 this 关键字,并且这里没有var 关键字. this.age; 在使用时,先是 this 关键字,之后的点语 ...
- mariabd mysql升级mariadb
还有错误 [root@localhost /]# mysqldump --all-databases --user=root --password --master-data > backupd ...
- zabbix监控一个机器上的多个java进程的jvm
一.监控安装部署 1.1 JVM端口配置 (/bqhexin/tomcat/bin/catalina.sh)在安装的tomcat路径,找到catalina.sh文件. vim编辑并添加: catali ...
- 文献阅读报告 - Social LSTM:Human Trajectory Prediction in Crowded Spaces
概览 简述 文献所提出的模型旨在解决交通中行人的轨迹预测(pedestrian trajectory prediction)问题,特别是在拥挤环境中--人与人交互(interaction)行为常有发生 ...
- php对象:__autoload()函数及单入口文件,__set(), __get(), get_class_methods(),get_class_vars()
__autoload():当类中找不到相关类的时候,会自动执行__autoload()函数,可以自动加载相关文件 __set() : 当对类的私有变量进行调用赋值时,自动调用该方法. __get() ...
- F5 基本原理介绍(转)
原文链接:http://kuaibao.qq.com/s/20180308G1NPIS00?refer=cp_1026文章来源:企鹅号 - 民生运维 1. 负载均衡的基本单位 目前负载均衡设备的基本处 ...
- java8 String intern()
public class Solution { public static void main(String[] args) { String a = new String("he" ...
- JXCPC 试题册
JXCPC 试题册 Input file: standard input Output file: standard output Time limit: 1s Memory limit: 256 m ...
- iOS 内购相关
iOS 内购相关 下面总结一下过往订阅和内购的项目的代码方面的实现细节和注意事项,特别是掉单方面的处理. 后台的协议.商品ID.银行卡.内购类型.沙盒账号测试人员都由运营或者产品在苹果后台中申请处理. ...