第一节,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. Servlet接口、GenericServlet类、HttpServlet类

    Servlet是最顶层的接口,其提供的方法有: init(ServletConfig config):void // 初始化 getServletConfig():ServletConfig // 取 ...

  2. [ 转载 ] get和post的区别

    GET和POST两种基本请求方法的区别   GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 最直观的区别就是GET把参数包含在URL中,POST通过r ...

  3. BZOJ.3139.[HNOI2013]比赛(搜索 Hash)

    题目链接 不会搜索了.. DFS()中两个参数,枚举每两个队伍的比赛结果(分配当前队伍的分数). 可以发现方案数量与具体哪只球队得了多少分无关,只与当前比赛的队伍数量和得分序列的组成有关.可以记忆化搜 ...

  4. ScrollView中嵌套GridView,Listview的办法

    按照android的标准,ScrollView中是不能嵌套具有滑动特性的View的,但是有时如果设计真的有这样做的需要,或者为了更方便简单的实现外观(比如在外在的大布局需要有滑动的特性,并且内部有类似 ...

  5. hdu 4451 37届金华赛区 J题

    题意:给出衣服裤子鞋子的数目,有一些衣服和裤子,裤子和鞋子不能搭配,求最终的搭配方案总数 wa点很多,我写wa了很多次,代码能力需要进一步提升 #include<cstdio> #incl ...

  6. phpexcel错误 You tried to set a sheet active by the out of bounds index: 1解决办法

    $objPHPExcel->createSheet($k);

  7. VSCode换行符

    如果要显示换行符:\r\n 如果要替换显示出来的\n,替换上要用正则表达式,然后使用\r\n. 如果要直接换行,\n

  8. STM32 通用定时器相关寄存器

    TIMx_CR1(控制寄存器1) 9-8位:CKD[1:0]时钟分频因子,定义在定时器时钟(CK_INT)频率与数字滤波器(ETR,TIx)使用的采样频率之间的分频比例. 定义:00(tDTS = t ...

  9. 图解tensorflow 源码分析

    http://www.cnblogs.com/yao62995/p/5773578.html https://github.com/yao62995/tensorflow

  10. Delphi2010 RTTI + Attribute 简单实现ORM实例

    1.支持ORM,最基础的两个信息是表的信息和字段信息.这两个信息,如果用Attribute 来辅助,代码更简洁和可读性更好.可以把属性名当做真实字段名,也可以将特性里的属性当成真实姓名,再加上字段标题 ...