什么是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表达式的更多相关文章

  1. Java8新特性-Lambda表达式是什么?

    目录 前言 匿名内部类 函数式接口 和 Lambda表达式语法 实现函数式接口并使用Lambda表达式: 所以Lambda表达式是什么? 实战应用 总结 前言 Java8新特性-Lambda表达式,好 ...

  2. 【Java8新特性】你知道Java8为什么要引入Lambda表达式吗?

    写在前面 这是一道真实的面试题,一个读者朋友出去面试,面试官竟然问他这样一个问题:你说说Java8中为什么引入Lambda表达式?引入Lambda表达式后有哪些好处呢?还好这个朋友对Java8早有准备 ...

  3. 乐字节-Java8新特性-Lambda表达式

    上一篇文章我们了解了Java8新特性-接口默认方法,接下来我们聊一聊Java8新特性之Lambda表达式. Lambda表达式(也称为闭包),它允许我们将函数当成参数传递给某个方法,或者把代码本身当作 ...

  4. Java 8 新特性 - Lambda表达式

    Lambda表达式 vs 匿名类既然lambda表达式即将正式取代Java代码中的匿名内部类,那么有必要对二者做一个比较分析.一个关键的不同点就是关键字 this.匿名类的 this 关键字指向匿名类 ...

  5. C#10新特性-lambda 表达式和方法组的改进

    C# 10 中对Lambda的语法和类型进行了多项改进: 1. Lambda自然类型 Lambda 表达式现在有时具有"自然"类型. 这意味着编译器通常可以推断出 lambda 表 ...

  6. java8新特性——Lambda表达式

    上文中简单介绍了一下java8得一些新特性,与优点,也是为本次学习java8新特性制定一个学习的方向,后面几篇会根据上文中得新特性一一展开学习.本文就从java8新特性中比较重要的Lambda表达式开 ...

  7. java8新特性-lambda表达式和stream API的简单使用

    一.为什么使用lambda Lambda 是一个 匿名函数,我们可以把 Lambda表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...

  8. Java8新特性 - Lambda表达式 - 基本知识

    A lambda expression is an unnamed block of code (or an unnamed function) with a list of formal param ...

  9. Java8 新特性lambda表达式(一)初始

    本篇参考Richard Warburton的 java8 Lambdas :Functional Programming for the Masses 学习lambda表达式之前,需要知道什么是函数式 ...

随机推荐

  1. java中的字符串String

    一.String简介d 参考:https://www.cnblogs.com/zhangyinhua/p/7689974.html String类代表字符串. java.lang.String: Ja ...

  2. 【机器学习实战学习笔记(1-1)】k-近邻算法原理及python实现

    笔者本人是个初入机器学习的小白,主要是想把学习过程中的大概知识和自己的一些经验写下来跟大家分享,也可以加强自己的记忆,有不足的地方还望小伙伴们批评指正,点赞评论走起来~ 文章目录 1.k-近邻算法概述 ...

  3. UVA_12697 满足条件的最短连续和 线段树维护

    好印象深刻的题,前天选拔赛给跪了.怪我这种关键题没敲出来. 题意很简单,给你一串无规则的数列,再给个m值,求出满足 数列和>=m的长度最小的连续子串...确实一开始卡住了,因为看数据肯定是nlo ...

  4. DevOps专题|基础Agent部署系统

    随着京东云业务规模.管理机器规模的扩大,各类agent也在逐渐增多,如日志agent.监控agent.控制系统agent等.这对agent的部署.升级.状态维护提出了很高的要求,一旦某个全局agent ...

  5. [安洵杯 2019]easy_serialize_php

    0x00 知识点 PHP反序列化的对象逃逸 任何具有一定结构的数据,只要经过了某些处理而把自身结构改变,则可能会产生漏洞. 参考链接: https://blog.csdn.net/a3320315/a ...

  6. zabbix安装及配置

    一.安装zabbix_server 二.安装zabbix_agent 三.zabbix配置详解

  7. DLL对应的导入库一定会生成的

    测试代码: #pragma once #define TESTDEPEND_EXPORTS #ifdef TESTDEPEND_EXPORTS #define TESTDEPEND_API __dec ...

  8. .NET技术-3.0. 日志插件 log4net

    .NET技术-3.0. 日志插件 log4net 背景:框架 NetFramework3.5 1. 新建控制台程序 2. 程序包管理器控制台中 增加 Nuget包 Install-Package lo ...

  9. HashMap的fast-fail和ConcurrentHashMap的fail-safe实例

    声明:迁移自本人CSDN博客https://blog.csdn.net/u013365635 Java HashMap遍历过程中如果元素被修改会导致遍历失败,ConcurrentHashMap则不会有 ...

  10. i春秋-web-爆破-1

    题目内容:flag就在某六位变量中. 题目 include "flag.php"; $a = @$_REQUEST['hello']; if(!preg_match('/^\w*$ ...