• 最新论文
  • 工业极简主义颠覆波普装饰:Prada 2016早春系列广告大片 北京昌平冠雅苑烂尾楼陷阱重重 屡次无证卖房 兴业投资:中东紧张局势加剧 油价飙升至9个月高位 交通运输部:ETC“二合一”联名卡存盗刷风险 媒体解读12条外汇管理新措施:简化取消和放开 北京昌平冠雅苑烂尾楼陷阱重重 屡次无证卖房 北京昌平冠雅苑烂尾楼陷阱重重 屡次无证卖房 交通运输部:ETC“二合一”联名卡存盗刷风险 工业极简主义颠覆波普装饰:Prada 2016早春系列广告大片 北京昌平冠雅苑烂尾楼陷阱重重 屡次无证卖房 从入门到入土:Lambda完整学习指南,包教包会! 媒体解读12条外汇管理新措施:简化取消和放开 交通运输部:ETC“二合一”联名卡存盗刷风险
  • 推荐论文
  • 工业极简主义颠覆波普装饰:Prada 2016早春系列广告大片 北京昌平冠雅苑烂尾楼陷阱重重 屡次无证卖房 兴业投资:中东紧张局势加剧 油价飙升至9个月高位 交通运输部:ETC“二合一”联名卡存盗刷风险 媒体解读12条外汇管理新措施:简化取消和放开 北京昌平冠雅苑烂尾楼陷阱重重 屡次无证卖房 北京昌平冠雅苑烂尾楼陷阱重重 屡次无证卖房 交通运输部:ETC“二合一”联名卡存盗刷风险 工业极简主义颠覆波普装饰:Prada 2016早春系列广告大片 北京昌平冠雅苑烂尾楼陷阱重重 屡次无证卖房 从入门到入土:Lambda完整学习指南,包教包会! 媒体解读12条外汇管理新措施:简化取消和放开 交通运输部:ETC“二合一”联名卡存盗刷风险
  • 热门标签
  • 日期归档
  • 从入门到入土:Lambda完整学习指南,包教包会!

    来源:www.zodiac02.com 发布时间:2020-03-09

    什么是λ表达式

    λ表达式是Java SE 8中的一个重要新特性。Lambda表达式允许您用表达式替换函数接口。与方法一样,Lambda表达式提供了一个正常的参数列表和一个使用这些参数的主体(主体,可以是表达式或代码块)。Lambda表达式也增强了集合库。

    Java Lambda表达式的一个重要用途是简化一些匿名内部类的编写。事实上,Lambda表达式不仅是匿名内部类的语法糖,而且JVM内部也通过invokedynamic指令实现了Lambda表达式。

    Lambda表达式语法

    Lambda表达式在Java语言中引入了一个新的语法元素和运算符。这个运算符是“-”并且被称为Lambda运算符或arrow运算符。它将Lambda分成两部分:

    左侧:指定Lambda表达式所需的所有参数

    右侧:指定Lambda体,即由Lambda表达式执行的函数。

    1。语法格式1:没有参数,没有返回值,Lambda主体只需要一个语句。

    示例:

    2。语法格式2: Lambda需要一个参数。

    示例:

    3。语法格式3:当Lambda只需要一个参数时,可以省略参数的括号。

    示例:

    4。语法格式4: Lambda需要两个参数,并且有一个返回值。

    示例:

    5。语法格式5:当Lambda主体只有一条语句时,可以省略return和大括号。

    示例:

    6。lambda表达式参数列表的数据类型可以省略或不写,因为JVM编译器通过上下文推断数据类型,即“类型推断”。

    示例:

    类型推断:Lambda表达式中的参数类型都是由编译器推断的。不需要在Lambda表达式中指定类型,程序仍然可以编译,因为javac根据程序的上下文在后台推断参数的类型。Lambda表达式的类型取决于上下上下文,由编译器推断。这就是所谓的“类型推理”

    使用λ表达式的要求

    也许你已经认为使用λ的基础必须是相应的?功能接口。

    function interface指的是内部只有一个抽象方法的接口。这与Java是一种强类型语言是一致的,这意味着您不能在代码的任何地方任意编写Lambda表达式。事实上,Lambda的类型就是相应函数接口的类型。Lambda表达式的另一个基础是类型推理机制。如果上下文信息足够,编译器可以推断参数表的类型,而无需显式命名。

    自定义函数接口

    自定义函数接口很简单,只需编写一个只有一个抽象方法的接口。

    上面代码中的

    FunctionalInterface是可选的,但是添加这个注释编译器将帮助您检查接口是否符合功能接口规范。就像添加

    Override注释检查函数是否重载一样。有了上面的接口定义,您可以编写类似如下的代码:

    详细的例子,请参考:

    Java内置了四个核心功能接口

    从入门到入土:Lambda完整学习指南,包教包会!

    Consumer Consumer Consumer Interface

    void accept(T T T);

    supplier provisioning interface

    T get();

    功能功能界面

    重新应用(t t);

    预测谓词接口

    布尔测试(T T);

    其他接口

    从入门到入土:Lambda完整学习指南,包教包会!

    方法引用和构造函数引用

    方法引用

    当已经有一个方法来实现要传递到Lambda的操作时,可以使用方法引用!

    方法引用的先决条件是什么?

    method引用所引用的方法的参数列表必须与函数接口中抽象方法的参数列表相同(完全相同)。

    method引用所引用的方法的返回值必须与函数接口中抽象方法的返回值相同(完全相同)。

    method reference通常有三种格式:

    instance object name :3360 instance method name

    class name :3360 static method name

    class name :3360 instance method name

    note:

    2 and 3 difference:如果Lambda参数列表中的第一个参数是实例方法的调用方,而第二个参数(或无参数)是实例方法的参数,则格式为:class name :3360 instance method name。

    方法引用:使用运算符“:3360”将方法名与对象或类名分开。

    1,object :3360 instance method

    2,class :3360 static method

    使用构造函数的先决条件是什么?

    构造函数参数表应该与接口中的抽象方法参数表一致!

    语法格式:

    类名:新

    array reference

    array reference和construction reference基本上与

    Collections中的公共函数接口

    Java8相同。添加了Java . util . function包,它包含公共函数接口,这是Lambda表达式的基础。Java集合框架还添加了一些接口来连接Lambda表达式。

    Java集合框架:

    从入门到入土:Lambda完整学习指南,包教包会!

    上图中绿色标记的接口类表示新的接口方法已经添加到Java8中。当然,由于继承,它们相应的子类将继承这些新方法。下表详细列出了这些方法。

    大多数新添加的方法需要java.util.function包下的接口,这意味着大多数这些方法都与Lambda表达式相关。

    Collection

    匿名内部类实现:

    中的新方法此方法的签名是void forEach(使用者操作),它对容器中的每个元素执行由操作指定的操作,其中使用者是一个函数接口,并且只有一个方法void accept(T t)要实现。

    匿名内部类实现:

    lambda表达式实现:

    匿名内部类实现:

    此方法被签名为布尔removeIf(谓词过滤器),用于删除容器中符合过滤器指定条件的所有元素,其中预测是一个函数接口,只有一个方法要实现,即布尔测试(T t)。

    匿名内部类实现:

    lambda表达式实现:

    匿名内部类实现:

    此方法被签名为布尔removeIf(谓词过滤器),用于删除容器中符合过滤器指定条件的所有元素,其中预测是一个函数接口,只有一个方法要实现,即布尔测试(T t)。

    匿名内部类实现:

    lambda表达式实现:

    匿名内部类实现:

    此方法被签名为布尔removeIf(谓词过滤器),用于删除容器中符合过滤器指定条件的所有元素,其中预测是一个函数接口,只有一个方法要实现,即布尔测试(T t)。

    匿名内部类实现:

    lambda表达式实现:

    匿名内部类实现:

    此方法被签名为布尔removeIf(谓词过滤器),用于删除容器中符合过滤器指定条件的所有元素,其中预测是一个函数接口,只有一个方法要实现,即布尔测试(T t)。

    分裂器可以像迭代器一样一个接一个或者分批迭代。批量迭代可以降低迭代成本。

    拆分器是可拆分的,拆分器可以被拆分器调用?TrySplit()方法试图分成两部分。一个是这个,另一个是新归还的。这两个迭代器表示的元素不重叠。

    load可以通过为多线程调用Spliterator.trySplit()方法(多次)来拆分。

    Stream()和parallelStream()

    Stream()和parallelStream()分别返回容器的流视图表示,只是parallelStream()返回并行流。流是Java函数编程的核心类,具体内容将在后面单独介绍。

    被标记为void foreach(双用户操作),用于在每个Map上执行操作指定的操作,其中bibumer是一个函数接口,带有要实现的void accept (t,u)方法。

    匿名内部类实现:

    被标记为void foreach(双用户操作),用于在每个Map上执行操作指定的操作,其中bibumer是一个函数接口,带有要实现的void accept (t,u)方法。

    匿名内部类实现:

    Lambda表达式实现:

    匿名内部类实现:

    此方法被签名为布尔removeIf(谓词过滤器),用于删除容器中符合过滤器指定条件的所有元素,其中预测是一个函数接口,只有一个方法要实现,即布尔测试(T t)。

    implementation:

    这个方法与Lambda表达式无关,但它非常有用。该方法的签名是V putIfAbsent(K键,V值)。它的功能是只有在没有键值映射或者映射值为空时,才把值指定的值放入映射。否则,地图不会改变。该方法将条件判断和赋值合二为一,使用起来更加方便。

    我们都知道在映射中有一个移除(对象键)的方法,根据指定的键值来删除映射中的映射关系。Java8添加了移除(对象键,对象值)方法。只有当前映射中的键完全映射到值时,映射才会被删除,否则什么也不会做。

    replace()

    在Java7和之前,如果要替换映射中的映射关系,可以使用put(K键,V值)方法,该方法总是用新值替换原始值。为了更准确地控制替换行为,Java8在映射中添加了两个replace()方法,如下所示:

    replace(K键,V值),只有在当前映射中存在键的映射时,才使用值替换原始值,否则什么也不做。

    replace (kkey,voldValue,vonewValue),仅当当前映射中的键映射存在并且等于旧值时,才使用新值替换原始值,否则不执行任何操作。

    replaceAll()

    此方法被签名为replaceAll(双函数函数)。它的功能是在每个映射上执行由函数指定的操作,并用函数的执行结果替换原始值,其中双函数是一个函数接口,带有要实现的方法重新应用(t t,u)。

    匿名内部类实现:

    lambda表达式实现:

    merge()

    此方法被签名为merge (kkey,vvalue,bifunctionremapping函数)。

    函数是:

    如果映射中对应键的映射不存在或为空,则该值(不能为空)与该键相关联;

    否则,将执行重映射功能。如果执行结果不为空,则结果将与键相关联。否则,将从映射中删除键的映射。

    参数中的BiFunction函数接口已经介绍过了,有一个方法要实现,那就是重新应用(t t,u)。虽然

    merge()方法在语义上很复杂,但是它的用法非常清楚。常见的情况是将新的错误信息拼接到原始信息上,例如:

    compute()

    此方法的签名是compute (kkey,bifunction reMappingFunction),用于将重新映射函数的计算结果与键相关联。如果计算结果为空,则从映射中删除键的映射。

    ComputeInformate()

    此方法被签名为v computeFacent(kkey,函数映射函数)。其功能是仅在当前映射中没有键值映射或映射值为空时调用mappingFunction,并在mappingFunction执行结果不为空时将结果与键相关联。

    Function是一个函数接口,带有一个要实现的方法。

    computeIfAbsent()通常用于为映射的键值建立初始化映射。例如,如果我们想要实现一个多值映射,映射的定义可以是映射。要将新值放入映射,我们可以通过下面的代码实现它:

    Implement:

    使用ComputeFabSent()将条件判断和添加操作结合起来,使代码更加简洁。

    computeIfPresent()

    此方法由vccomputerriprescent(kkey,双函数重映射函数)签名,它与computeIfPresent()相反。也就是说,只有当当前映射中存在键值映射并且它不为空时,才会调用ReView函数。如果remappingFunction的执行结果为空,则删除键的映射,否则,用结果替换键的原始映射。

    Stream

    对Java 7完全陌生。流不是数据结构,它只是数据源的视图。这里的数据源可以是数组、Java容器或I/O通道等。

    公共流接口继承关系如下:

    从入门到入土:Lambda完整学习指南,包教包会!

    ?“Java集合框架”的接口继承结构?

    图中的四个流接口是从BaseStream继承的,其中INTStream、LONGstream和DOUBLE stream对应于三种基本类型(int、long、DOUBLE,请注意它们不是包装类型),而STREAM对应于所有剩余类型的流视图。

    ?“Java集合框架”的接口继承结构?

    :

    的性能,并增加特定的接口功能。

    为什么不把IntStream等等设计成Stream的子接口呢?

    答案是尽管这些方法的名称相同,但返回类型不同。如果它们被设计为父子接口关系,这些方法不能共存,因为Java不允许只重载具有不同返回类型的方法。

    虽然在大多数情况下,流是由调用Collection.stream()方法的容器获得的,但流和集合有以下区别:

    没有存储。流不是数据结构,它只是某个数据源的视图,可以是数组

    为函数式编程而生。对流的任何修改都不会修改它后面的数据源。例如,对流执行过滤操作不会删除已过滤的元素,但会生成不包含已过滤元素的新流。

    空闲执行。对流的操作不会立即执行,并且在用户真正需要结果之前不会执行。

    可消费性。流只能“消耗”一次。一旦被遍历,它将变得无效。像容器的迭代器一样,它必须重新生成才能再次遍历。

    对流的操作分为两种类型,中间操作和终端操作,其特点是:

    中间操作总是懒洋洋地执行,调用中间操作只会生成一个新的流,用操作标记,如此而已。

    结束操作将触发实际计算。当计算发生时,中间操作累积的所有操作将以流水线方式执行,从而减少迭代次数。计算完成后,流将失败。

    下表总结了流接口的一些常用方法:

    从入门到入土:Lambda完整学习指南,包教包会!

    区分中间操作和结束操作的最简单方法是查看方法的返回值。大部分返回值是流,否则就是结束操作。

    stream方法使用

    stream,并且与函数接口有非常密切的关系,没有它,流就不能工作。

    function interface指的是内部只有一个抽象方法的接口。Lambda表达式通常用在函数接口出现的任何地方,因此没有必要记住函数接口的名称。

    forEach()

    方法被签名为void forEach(使用者操作),它对容器中的每个元素执行操作指定的操作,即遍历元素。

    因为forEach()是结束方法,上面的代码将立即执行,所有的字符串都将被输出。

    filter()

    函数原型是Streamfilter (predictpredict),用于返回只包含满足谓词条件的元素的流。

    以上代码将作为长度大于或等于3的字符串love和Java输出。请注意,由于filter()是一个中间操作,如果只调用filter(),将不会有实际的计算,因此不会输出任何信息。

    distinct()

    函数原型是Stream distinct(),它在删除重复元素后返回一个Stream。

    上述代码将在您被删除后输出字符串的剩余部分。

    sorted()

    有两个排序函数,一个是按自然顺序排序,另一个是使用自定义比较器排序。该函数的原型是流排序()和流排序(比较器)。

    map()

    函数原型是流映射(函数映射器),它返回由映射器对所有当前元素执行的结果组成的流。直观地说,每个元素都是根据某种操作进行转换的。流中元素的数量在转换前后不会改变,但元素的类型取决于转换后的类型。

    flatMap()

    函数原型是Streamflagmap(函数映射器),用于对每个元素执行映射器指定的操作,并以映射器返回的流中的所有元素作为最终返回结果来形成新的流。很难说。通俗地说,flatMap()的功能相当于通过“展平”原始流中的所有元素而形成的流。转换前后,元素的数量和类型可能会发生变化。

    flow的缩减操作也称为折叠操作,这是一个通过某种连接动作将所有元素汇总成汇总结果的过程。对元素求和,找到最大值或最小值,找到元素的总数,并将所有元素转换成列表或集合都是常规操作。Stream类库有两个常用的约简()和collect(),以及一些为简化编写而设计的特殊约简操作,如sum()、max()、min()、count()等。

    最大值或最小值是一种众所周知的约定操作(至少对方法来说语义如此)。我们专注于减少()和收集(),这是神奇的地方。

    reduce操作可以从一组元素中生成一个值。sum()、max()、min()、count()等。都是精简操作。它们被设置为函数只是因为它们是常用的。reduce()的方法定义有三种重写形式:

    reduce操作可以从一组元素中生成一个值。sum()、max()、min()、count()等。都是精简操作。它们被设置为函数只是因为它们是常用的。reduce()的方法定义有三种重写形式:

    可选reduce(二进制运算符累加器)

    t reduce (t恒等式,二进制运算符累加器)

    u reduce (u恒等式,双函数累加器,二进制运算符组合器)

    尽管函数定义越来越长,但语义没有改变。更多参数仅用于指示初始值(参数标识)或指定并行执行时多个部分结果的组合(参数组合器)。reduce()最常见的场景是从一堆值中生成一个值。

    具体做法:

    上面的代码将选择最长的单词love,其中Optional是一个值的容器,可以避免空值的麻烦。当然,你可以用这条小溪。max (comparator)方法达到同样的效果,但是reduce()有它自己的原因。

    parameter 2:

    string映射到length。

    并加到当前总数中。

    这显然是一个两步操作。使用reduce()函数将两个步骤合二为一更有助于提高性能。如果您想使用map()和sum()的组合来实现上述目的,也是可能的。

    reduce()擅长生成值。如果您想从流中生成一个复杂的对象,如集合或地图,该怎么办?

    collect()

    如果您发现一个在流接口中找不到的函数,十有八九您可以通过collect()来实现它。Collect()是流接口最灵活的方法之一。学习它是对Java函数编程的真正介绍。

    示例:

    上面的代码分别列出了如何将流转换为列表、集合和映射。尽管代码语义很清楚,我们仍然有几个问题:

    Function.identity()做什么?“字符串:长度”是什么意思?什么是“收藏家”?

    interface

    Function的静态方法和默认方法是接口,那么Function.identity()是什么意思呢?这有两种解释:

    Java 8允许向接口添加特定的方法。接口中有两个特定的方法,默认方法和静态方法。identity()是函数接口的静态方法。Identity()返回一个Lambda表达式对象,其输出与输入相同,这相当于一个t-t

    形式的Lambda表达式。上面的解释是否让您有更多疑问?不要问我为什么接口中会有特定的方法,也不要告诉我你认为t-t比identity()方法更直观。我会告诉你,接口中的默认方法是一个无助的举动。在Java 7之前,向已定义的接口添加新的抽象方法是非常困难的,甚至是不可能的,因为所有实现接口的类都必须重新实现。想象一下向集合接口添加一个stream()抽象方法。默认方法用于解决这个尴尬的问题,新添加的方法直接在接口中实现。既然已经引入了默认方法,为什么不添加静态方法来避免特殊的工具类呢?

    method references

    语法形式,如String:length,被称为方法引用,用于替换某些特定形式的Lambda表达式。如果Lambda表达式的全部内容是调用现有的方法,则Lambda表达式可以被方法引用替换。方法引用可以细分为四类:

    从入门到入土:Lambda完整学习指南,包教包会!

    Collector

    collector是为Stream.collect()方法定制的工具接口(类)。考虑一下将一个流转换成一个容器(或地图)需要做什么?我们至少需要两样东西:

    目标容器是什么?数组列表,哈希表,树形图。

    如何向容器中添加新元素?添加()或映射放()。

    如果协议是并行执行的,您还需要告诉collect()如何将多个部分结果合并成一个。

    结合以上分析,collect()方法定义为R collect(供应商、双用户累加器、双用户组合器),这三个参数依次对应于以上三个分析。

    但是,每次调用对方付费()时,传入这三个参数太麻烦了。收集器是这三个参数的简单封装,所以R收集器的另一个定义是(收集器收集器。

    Collectors工具类可以通过静态方法生成各种常见的收集器。例如,如果您想将流简化为列表,您可以通过以下两种方式来实现:

    通常,我们不需要手动指定collect()的三个参数,而是调用collector方法,参数中的Collector对象大多是通过Collectors工具类直接获得的。实际上传的收集器的行为决定了collect()的行为。

    使用Collection()生成集合

    有时我们可能需要手动指定容器的实际类型。这一要求可以通过收集器来满足。至收集(供应商收集工厂)方法。

    Connection timed out after milliseconds

    友情链接: