博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java8 lambda 简介
阅读量:6219 次
发布时间:2019-06-21

本文共 3505 字,大约阅读时间需要 11 分钟。

为什么要lambda表达式

        大多数程序员或者说大多数团队写代码的最高目标是**干净(易读)、易于维护(好改)**的代码,这也就是lambda表达式被引入java8中的根本原因。

        如同面向对象是对于数据的抽象,函数式编程是对行为的抽象。java8提供了高效的并行算法用以处理大型数据集合,这些算法是即是由stream提供的。但是由于不同的数据集合处理行为不一样,通用的jdk封装不可能面面俱到,所以提供了一些列接口,允许用户定义具体的行为从而完成相应的目标。这些具体的行为就是通过lambda表达式提供给stream对象的。这是lambda表达式被引入的另一个重要原因

        以下提供两个例子来感受下函数式编程的威力,体会下行为抽象的好处

// 匿名内部类List
tmp1 = Arrays.asList(1,2,2,3,4,51,3,4,5);tmp1.sort(new Comparator
() { @Override public int compare(Integer o1, Integer o2) { return o1 - o2; }}); // labmda表达式List
tmp2 = Arrays.asList(1,2,2,3,4,51,3,4,5);tmp2.sort((x , y) -> x - y);复制代码

lambda表达式是什么

        鄙人浅见,lambda表达式即为对行为的抽象。如同一个具体对象表示着某一种格式的数据一样,一个具体的lambda表达式表示一个行为。

形式

(parameters) -> expression(parameters) ->{ statements; }复制代码

lambda表达式的类型

        函数接口是只有一个抽象方法的接口,用作lambda表达式的类型

  • 函数接口

四个基本的函数接口

@FunctionalInterfacepublic interface Consumer
{ void accept(T t);}@FunctionalInterfacepublic interface Function
{ R apply(T t);} @FunctionalInterfacepublic interface Predicate
{ boolean test(T t);}@FunctionalInterfacepublic interface Supplier
{ T get();} 复制代码

其他的由jdk提供的函数式接口,基本上是这四个的某种组合或者变种,当然也可以自己定义函数接口,出于编程的良好习惯自定义的函数接口,要使用**@FunctionalInterface**修饰

  • 基本类型

        由于包装类和原始类型在java虚拟机中性能上差距很大,jdk提供了专门用于long、double、int三者的函数式接口以提高性能、减小内存占用,同样的后文中提到的stream中也提供了很多对这些类型进行过优化的操作。应该尽可能多的使用这中特殊优化过的操作。

  • 重载解析

        虽然上文说了函数接口就是lambda表达式的类型,但是实际情况中往往难以直接得到其类型。以下的例子中同样的表达式却有两个不同的类型

@FunctionalInterfacepublic interface IntPred {    boolean test(Integer value);}public class Test {    int a = 2;    boolean check(Predicate
predicate) { System.out.println("predicate"); return predicate.test(a); } boolean check(IntPred intPred) { System.out.println("intPred"); return intPred.test(a); } public static void main(String[] args) { Test test = new Test(); test.check(t -> {
return t > 0;}); // ① }}复制代码

        在①处的代码无法通过编译,因为编译器没法确定具体类型是什么。造成这种情况的原因在于类型推断。假设lambda表达式出现的位置需要类型classA(术语称之为目标类型),只要lambda表达式入参、返回值等等和classA中那个唯一的方法匹配,则该lambda表达式的类型就是classA。所以同样的表达式出现在不同的位置可能会产生不同的类型。

        这种类型推断相比于显式指定类型不够准确,在上述例子中编译器就无法确定lambda表达式的类型,从而不知道要重载哪个方法,所以报错。

  • 类型推导

        java中lambda表达式的类型推导遵循以下规则

        (1)如果只有一个可能的目标类型,由相应的函数接口里的参数类型推导得出

        (2)如果有多个可能的目标类型,由最具体的类型推导得出

        (3)如果有多个可能的目标类型且最具体的类型不明确,则需要人为指定类型

private void overload(Object a) {	System.out.println("object"); // ①}private void overload(String a) {	System.out.println("string"); // ②}overload("abc") // ③复制代码

        以上伪代码用于说明何为最具体,③处的重载调用,最终会是②处的代码被执行,因为String更具体。

引用值

        lambda表达式引用局部变量只能使用final变量或者既成事实的final变量。final变量即为用final修饰的变量,既成事实的final变量是指这个变量虽然无final修饰,但是如果给它加上final修饰编译器也不会报错。

String name = getUserName();name = "hjjk";button.addActionListerner(e -> System.out.println(name)); // 无法通过编译复制代码

方法引用

方法引用是一种特殊的lambda表达式,可读性更好,更简洁。每一个方法引用都可以用一般的lambda替换

类型 形式 等价形式
静态 RefType::staticMethod (args) -> RefType.staticMethod(args)
绑定实例 expr::instMethod (args) -> expr.instMethod(args)
未绑定实例 RefType::instMethod (args0, rest) -> args0.instMethod(rest)
构造器 ClsName::new (args) -> new ClsName(args)

以下例子转自

构造器引用:它的语法是Class::new,或者更一般的Class< T >::new实例如下:

final Car car = Car.create( Car::new );final List< Car > cars = Arrays.asList( car );复制代码

静态方法引用:它的语法是Class::static_method,实例如下:

cars.forEach( Car::collide );复制代码

特定类的任意对象的方法引用:它的语法是Class::method实例如下:

cars.forEach( Car::repair );复制代码

特定对象的方法引用:它的语法是instance::method实例如下:

final Car police = Car.create( Car::new );cars.forEach( police::follow );复制代码

lambda和stream

未完待续。。。

转载地址:http://pfmja.baihongyu.com/

你可能感兴趣的文章
CryptoJS base64使用方法
查看>>
利用python批量修改MySQL表结构
查看>>
Metasploit 渗透测试手册第三版 第一章 Metasploit快速入门(翻译)
查看>>
021-cdh6.2+kylin2.6.2
查看>>
Linux - 进程
查看>>
从DevOps到ContainerOps
查看>>
版本控制:Git、Github 和 SVN的使用
查看>>
可变参数范例
查看>>
内核必须懂(三): 重编Ubuntu18.04LTS内核4.15.0
查看>>
遍历对象实例的属性和方法
查看>>
React组件
查看>>
论战,交易挖矿模式,能走多远?
查看>>
Vue中axios的封装
查看>>
实现一个简单版本的Vue及源码解析(一)
查看>>
GCD(二) dispatch_barrier
查看>>
Android 复杂的列表视图新写法 MultiType (v3.1.0 修订版)
查看>>
【前端记-1】你不知道的前端缓存
查看>>
AJAX发送请求、同源策略与CORS跨域
查看>>
顶尖AI无法识别简单图案?因为人类已经无法理解它们了
查看>>
用 Node.js 写一个多人游戏服务器引擎
查看>>