第一节,Lambda管中窥豹
   可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式,它没有名称,但它有参数列表、函数主题和返回值。
   本节介绍了Lambda表达式的语法,它包括参数列表、箭头、Lambda的主体,其中Lambda主体可以包括多行,这个时候必须用大括号把它括起来。
   本节的最后作者给出了Lambda语法的几个例子,让我们来辨别什么是合法的Lambda表达式语法,其中在没有大括号的时候用return是不对的,带有大括号的时候用单行的表达式也是不对的。
 
第二节,在哪里以及如何使用Lambda
   我们可以在函数式接口上使用Lambda表达式,那么本节中作者也提出了什么是函数式接口?函数式接口就是只有一个抽象方法的接口,比如传统Java里面的Comparator, Runnable, EventListener,Callable, PrivilegedAction。
   然后这里作者又提出了默认方法的概念。所谓的默认方法就是在类没有对接口方法进行实现的时候,在接口主体也为方法提供了默认实现的方法,哪怕有很多默然方法,只要接口只有一个抽象方法,那它就仍然是一个函数式接口。
   作者在这里给了几个让我们辨认什么是函数式接口的例子,有两个错误的例子,一个是里面一个借口都没有定义的,另外一个里面虽然自定义一个接口,但是他还从父接口中继承了一个抽象接口。
   函数式接口的抽象方法的签名,基本上就是Lambda表达式的签名,我们将这种抽象方法叫做函数描述符。比如Runnnable接口可以看做一个什么也不接受,什么也不返回的函数的签名。
   关于可以在哪里使用Lambda,其实有很多,比如可以作为函数的入参、作为函数的返回值、又或者把它赋值给一个局部变量。后作者提到了一个叫做@FunctionalInterface的注解
 
第三节,把Lambda付诸实践,环绕执行模式。
   所谓的环绕执行模式其实就类似于以前我们学到的模版方法模式,这里使用的是try...catch的例子。当然在模板方法中,我们一般是通过在子类重写抽象方法的形式来让模板方法具有不同的行为,在本节中,我们可以通过表达式的方式直接把代码传递给方法,从而实现不同的行为。
 
第四节,使用函数式接口
   函数式接口很有用,因为抽象方法的签名可以描述Lambda表达式的签名,函数式接口的抽象方法的签名称为函数描述符,所以为了运用不同的表达式,你需要一套能够描述常见描述函数描述符的函数式借口。在Java的API中已经有了几个函数式的接口。比如Comparable, Runnable ,Callable, 在Java8中,设计师在java.util.funtion包又添加了几个新的函数是接口,比如Predicate ,Consumer ,Funtion。
   然后作者又提到了这种函数式接口对于基本类型的特化,为什么要特化呢,因为对于原始类型的装箱和拆箱性能比较低。有了特化之后就可以避免这种装箱拆箱的操作。
   然后再在p46页中给出了一个表格,其中列出了在Java8中的常用的函数式接口。主要就是断言、消费者、函数,以及它们的单参数、多参数、基本类型特化的各种变体。
   在这里作者提到了任意函数式接口都不允许抛出受检异常,如果你需要Lambda表达式来抛出异常,有两种方法:第一种是定义一个自己的函数是接口,并申明受检异常;第二,把Lambda包在一个try catch块中。
 
第五节,类型检查,类型推断以及限制
   Lambda的类型是从使用Lambda的上下文中推断出来的。上下文中Lambda表达式需要的类型称为目标类型。有了目标类型的概念,那么同一个Lambda表达式就可以与不同的函数式接口联系起来,只要他们的抽象方法签名能够兼容就行。大家可能还记得在Java7中就已经引入的菱形运算符,利用泛型推断从上下文中推断类型的思想。
   这里还有一个特殊的void 的兼容规则, 也就是说,如果一个Lambda的主体是一个语句表达式,他就和一个返回void 的函数描述符兼容。
   第四小节,使用局部变量
   我们迄今为止所介绍的所有Lambda表达式都只用到了其主体里面的参数,但是人们还是也允许使用自由变量,就像匿名类一样。所谓自由变量,就是在外层作用域中定义的变量。虽然它可以使用自由变量,但其实是有一些限制的。Lambda可以没有限制的使用实例变量和静态变量,但是局部变量必须显示的声明为final。换句话说就是lambda表达式,只能捕获指派给他们的局部变量一次。之所以会有这种限制,是因为局部变量是分配在栈上的,而实例变量和静态变量是分配在堆栈的。基于java中对于自由变量的这种限制,所以它实际上不具有JS中的那种闭包的概念。
 
第六节,方法引用
   方法应用可以被看作仅仅调用特定方法的Lambda的一种快捷写法,它的基本思想是,如果Lambda代表的只是直接调用这个方法,那最好还是用名称来调用它,而不是去描述如何调用它。因为显示的指定方法的名称,你的代码的可读性会更好。
 
   在这里,作者给出了,三种类型的方法引用:
   第一种,指向静态方法的方法应用,比如integer的parseInt方法。
   第二种,只想问你类型实例方法的方法已有,比如String的 length方法。
   第三种,指向现有对象的实例方法的方法应用,这个所谓的现有对象,不是表达式的入参,而是上文提到的那种自由变量,用就是外层作用域中的变量。
   第二小节,构造函数引用
   也就是说对于一个现有的构造函数,你可以利用它的名称和关键字new,来创建它的一个引用,像这样Classname::new 。但是这个方法应用创建好之后赋值给谁就有点讲究了,这主要是根据这个构造函数的参数的多少而有所不同,比如说没有参数、一个参数、两个参数等等,分别可以给Supplier, Function ,BiFunction,。
   构造函数应用的一个典型应用就是用来构造简单工厂方法,直接把每一个类的构造函数注册到工厂的字典里面去。
 
第七节,lambda和方法应用实战
   这一节唯一要注意的就是Comparator的那个看comparing 静态辅助方法。他可以接受一个function来提取comparable键值 ,并生成一个Comparator 对象,他的实现代码如下:
 public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
}
 
第八节,复合Lambda 表达式的有用方法
   这一节主要列出了Java8新提供的几个函数式接口:Comparator, Function, Predicate新提供的默认方法来作为复合方法。有了复合方法之后,就意味着你可以把多个简单的Lambda复合成复杂的表达式。比如你可以让两个谓词做一个or操作,组合成一个更大的谓词,而且你还可以让一个函数的结果成为另一个函数的输入,你可能会想函数式接口怎么可能有更多的方法呢?窍门在于我们即将介绍的方法都是默认方法,也就是说它们不是抽象方法。然后作者详细地给出了,比较器复合,谓词复合 、函数复合。具体都包含哪些复合函数就要自己去看了。这些复合函数组合起来还确实是挺神奇的。
 

读书笔记,《Java 8实战》,第三章,Lambda表达式的更多相关文章

  1. 第三章 Lambda表达式

    第三章 Lambda表达式 3.1 函数式编程思想概述 在数学中,函数就是有输入量.输出量的一套计算方案,也就是“拿什么东西做什么事情”.相对而言,面向对象过分强调“必须通过对象的形式来做事情”,而函 ...

  2. 读书笔记 - js高级程序设计 - 第三章 基本概念

    启用严格模式 "use strict" 这是一个 pragma 编译指示 让编码意图更清晰  是一个重要原则 5种简单数据类型 Undefined Null Boolean Num ...

  3. [读书笔记] R语言实战 (三) 图形初阶

    创建图形,保存图形,修改特征:标题,坐标轴,标签,颜色,线条,符号,文本标注. 1. 一个简单的例子 #输出到图形到pdf文件 pdf("mygrapg.pdf") attach( ...

  4. 读书笔记 - js高级程序设计 - 第七章 函数表达式

      闭包 有权访问另一个函数作用域中的变量的函数 匿名函数 函数没有名字 少用闭包 由于闭包会携带包含它的函数的作用域,因此会比其它函数占用更多的内存.过度使用闭包可能会导致内存占用过多,我们建议读者 ...

  5. 【读书笔记《Bootstrap 实战》】6.单页营销网站

    我们已经掌握了很多实用 Bootstrap  的重要技能.现在,是时候拿出更多的创意来帮助客户实现他们全方位在线营销的愿望了.此次将带领大家做一个漂亮的单页高端营销网站. 主要任务如下: □ 一个大型 ...

  6. 《C#从现象到本质》读书笔记(九)第11章C#的数据结构

    <C#从现象到本质>读书笔记(九)第11章C#的数据结构 C#中的数据结构可以分为两类:非泛型数据结构和泛型数据结构. 通常迭代器接口需要实现的方法有:1)hasNext,是否还有下一个元 ...

  7. 《深入了解java虚拟机》高效并发读书笔记——Java内存模型,线程,线程安全 与锁优化

    <深入了解java虚拟机>高效并发读书笔记--Java内存模型,线程,线程安全 与锁优化 本文主要参考<深入了解java虚拟机>高效并发章节 关于锁升级,偏向锁,轻量级锁参考& ...

  8. Rxjava2实战--第三章 创建操作符

    Rxjava2实战--第三章 创建操作符 Rxjava的创建操作符 操作符 用途 just() 将一个或多个对象转换成发射这个或者这些对象的一个Observable from() 将一个Iterabl ...

  9. 《C#从现象到本质》读书笔记(八)第10章反射

    <C#从现象到本质>读书笔记(八)第10章反射 个人感觉,反射其实就是为了能够在程序运行期间动态的加载一个外部的DLL集合,然后通过某种办法找到这个DLL集合中的某个空间下的某个类的某个成 ...

  10. 《C#从现象到本质》读书笔记(七)第9章 泛型

    <C#从现象到本质>读书笔记(七)第9章 泛型 泛型的三大好处:类型安全,增强性能(避免装箱和拆箱),代码复用. 泛型方法是传入的参数至少有一个类型为T(尚未制定的类型,根据微软的命名规则 ...

随机推荐

  1. Kali Linux 2017.3发布了

     Kali Linux 2017.3发布了 Kali Linux官方在11月21日发布Kali Linux 2017的第三个版本2017.3.这次发布变化相对不大,主要是设置面板风格发生改变,增加少量 ...

  2. BZOJ3009 : 集合

    取一棵生成森林,根据题目限制可得,与一个点相连的多余的边数是$O(\sqrt{m})$级别的. 对于树边,每个点维护3棵权值线段树,依次保存它的儿子里各个集合的边. 再开3*3个分块数组,记录多余边以 ...

  3. 简单分享apache封IP的方法

    1. 在配置文件里设置: 打开httpd.conf编辑:<Directory “/var/www/html”>     Options Indexes FollowSymLinks    ...

  4. QThreadPool线程池的使用,线程与Widget通过信号与槽的方式通信。

    因为QRunnable类并非继承自QObject,不能使用信号和槽,为了能够使用信号与槽和Widget通信,需要对QRunnable进行封装. 定义一个类QMyRunnable,该类首先继承自QObj ...

  5. OpenVPN搭建中tap与tun的实际使用区别

    tap俗称网桥模式,tun俗称路由模式,tap在二层,tun在三层,在实际应用中,其实以上这些知识概念,我是抄来的,具体的解释可以看以下参考链接. 下面将介绍在实际使用中的区别: 1.tap可以直接使 ...

  6. web网页上面调用qq

    <a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=2812415198&site=q ...

  7. An Isolated DAC Using PWM Output

    An Isolated DAC Using PWM Output Arduino‘s (ATmega328P) PWM outputs via analogWrite can be convenien ...

  8. 解决svn中文乱码的问题

    需要的工具:sqlitexiaz 工具下载: 链接:https://pan.baidu.com/s/1cz1Pvw 密码:yp64 1 首先在项目的根目录下,找到.svn(如果找不到,需要设置将隐藏文 ...

  9. [Go] 第一个单词首字母变大写:Ucfirst(),第一个单词首字母变小写:Lcfirst()

    import ( "unicode" ) func Ucfirst(str string) string { for i, v := range str { return stri ...

  10. delphi下实现ribbon界面的方法(一)

    http://www.cnblogs.com/shanmx/archive/2011/12/04/2275213.html