Lambda

  大年初二,大门不出二门不迈。继续学习!

函数式接口

  Lambda表达式其实就是实现SAM接口的语法糖,所谓SAM接口就是Single Abstract Method,即该接口中只有一个抽象方法需要实现,当然该接口可以包含其他非抽象方法。

  它关注方法具备什么样的功能,强调做什么,而不是以什么形式做。

  • 面向对象的思想:

    • 做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情.

  • 函数式编程思想:

    • 只要能获取到结果,谁去做的,怎么做的都不重要,重视的是结果,不重视过程

自定义函数式接口

  只要确保接口中有且仅有一个抽象方法即可

修饰符 interface 接口名称 {
public abstract 返回值类型 方法名称(可选参数信息);// public abstract 是可以省略的
// 其他非抽象方法内容
}

消费型接口

  消费型接口的抽象方法特点:有形参,但是返回值类型是void

接口名 抽象方法 描述
Consumer<T> void accept(T t) 接收一个对象用于完成功能
BiConsumer<T,U> void accept(T t, U u) 接收两个对象用于完成功能
DoubleConsumer void accept(double value) 接收一个double值
IntConsumer void accept(int value) 接收一个int值
LongConsumer void accept(long value) 接收一个long值
ObjDoubleConsumer<T> void accept(T t, double value) 接收一个对象和一个double值
ObjIntConsumer<T> void accept(T t, int value) 接收一个对象和一个int值
ObjLongConsumer<T> void accept(T t, long value) 接收一个对象和一个long值

供给型接口

  供给型接口的抽象方法特点:无参,但是有返回值

接口名 抽象方法 描述
Supplier<T> T get() 返回一个对象
BooleanSupplier boolean getAsBoolean() 返回一个boolean值
DoubleSupplier double getAsDouble() 返回一个double值
IntSupplier int getAsInt() 返回一个int值
LongSupplier long getAsLong() 返回一个long值

判断型接口

  判断型接口的抽象方法特点:有参,但是返回值类型是boolean结果

接口名 抽象方法 描述
Predicate<T> boolean test(T t) 接收一个对象
BiPredicate<T,U> boolean test(T t, U u) 接收两个对象
DoublePredicate boolean test(double value) 接收一个double值
IntPredicate boolean test(int value) 接收一个int值
LongPredicate boolean test(long value) 接收一个long值

功能型接口

  功能型接口的抽象方法特点:既有参数又有返回值

接口名 抽象方法 描述
Function<T,R> R apply(T t) 接收一个T类型对象,返回一个R类型对象结果
UnaryOperator<T> T apply(T t) 接收一个T类型对象,返回一个T类型对象结果
DoubleFunction<R> R apply(double value) 接收一个double值,返回一个R类型对象
IntFunction<R> R apply(int value) 接收一个int值,返回一个R类型对象
LongFunction<R> R apply(long value) 接收一个long值,返回一个R类型对象
ToDoubleFunction<T> double applyAsDouble(T value) 接收一个T类型对象,返回一个double
ToIntFunction<T> int applyAsInt(T value) 接收一个T类型对象,返回一个int
ToLongFunction<T> long applyAsLong(T value) 接收一个T类型对象,返回一个long
DoubleToIntFunction int applyAsInt(double value) 接收一个double值,返回一个int结果
DoubleToLongFunction long applyAsLong(double value) 接收一个double值,返回一个long结果
IntToDoubleFunction double applyAsDouble(int value) 接收一个int值,返回一个double结果
IntToLongFunction long applyAsLong(int value) 接收一个int值,返回一个long结果
LongToDoubleFunction double applyAsDouble(long value) 接收一个long值,返回一个double结果
LongToIntFunction int applyAsInt(long value) 接收一个long值,返回一个int结果
DoubleUnaryOperator double applyAsDouble(double operand) 接收一个double值,返回一个double
IntUnaryOperator int applyAsInt(int operand) 接收一个int值,返回一个int结果
LongUnaryOperator long applyAsLong(long operand) 接收一个long值,返回一个long结果
     
BiFunction<T,U,R> R apply(T t, U u) 接收一个T类型和一个U类型对象,返回一个R类型对象结果
BinaryOperator<T> T apply(T t, T u) 接收两个T类型对象,返回一个T类型对象结果
ToDoubleBiFunction<T,U> double applyAsDouble(T t, U u) 接收一个T类型和一个U类型对象,返回一个double
ToIntBiFunction<T,U> int applyAsInt(T t, U u) 接收一个T类型和一个U类型对象,返回一个int
ToLongBiFunction<T,U> long applyAsLong(T t, U u) 接收一个T类型和一个U类型对象,返回一个long
DoubleBinaryOperator double applyAsDouble(double left, double right) 接收两个double值,返回一个double结果
IntBinaryOperator int applyAsInt(int left, int right) 接收两个int值,返回一个int结果
LongBinaryOperator long applyAsLong(long left, long right) 接收两个long值,返回一个long结果

Lambda表达式语法

  其本质上,Lambda表达式是用于实现【函数式接口】的“抽象方法”

Lambda表达式语法格式

(形参列表) -> {Lambda体}

说明:

  • (形参列表)它就是你要赋值的函数式接口的抽象方法的 (形参列表),照抄

  • {Lambda体}就是实现这个抽象方法的方法体

  • -> 称为Lambda操作符(减号和大于号中间不能有空格,而且必须是英文状态下半角输入方式)

优化:Lambda表达式可以精简

  • 当{Lambda体}中只有一句语句时,可以省略{}和{;}

  • 当{Lambda体}中只有一句语句时,并且这个语句还是一个return语句,那么return也可以省略,但是如果{;}没有省略的话,return是不能省略的

  • (形参列表)的类型可以省略

  • 当(形参列表)的形参个数只有一个,那么可以把数据类型和()一起省略,但是形参名不能省略

  • 当(形参列表)是空参时,()不能省略

ArrayList<String> list = new ArrayList<>();
list.forEach((li) -> System.out.println("li = " + li));//void forEach(Consumer<? super T> action)

方法引用

  当 Lambda 体满足一些特殊的情况时,还可以再简化

    (1)Lambda体只有一句语句,并且是通过调用一个对象的/类的现有的方法来完成的

    (2)并且Lambda表达式的形参正好是给该方法的实参

  方法引用的语法格式:

    (1)实例对象名::实例方法

    (2)类名::静态方法

    (3)类名::实例方法

  说明:

    :: 称为方法引用操作符(两个 中间不能有空格,而且必须英文状态下半角输入)

    Lambda表达式的形参列表,全部在Lambda体中使用上了,要么是作为调用方法的对象,要么是作为方法的实参。

    在整个Lambda体中没有额外的数据。

构造器引用

  (1)当Lambda表达式是创建一个对象,并且满足Lambda表达式形参,正好是给创建这个对象的构造器的实参列表。

  (2) 当Lambda表达式是创建一个数组对象,并且满足Lambda表达式形参,正好是给创建这个数组对象的长度

  构造器引用的语法格式:

    类名::new

    数组类型名::new

Stream

  Stream API 提供了一种高效且易于使用的处理数据的方式。

  Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的多种操作,可以执行非常复杂的查找、过滤和映射数据等操作。

  Stream 是数据渠道,用于操作数据源(集合、数组等)所存储的元素序列。“集合指的是负责存储数据,Stream流指的是计算,负责处理数据!”

注意

  ①Stream 自己不会存储元素

  ②Stream 不会改变源对象。每次处理都会返回一个持有结果的新Stream。

  ③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

Stream 的操作三个步骤:

  1- 创建 Stream:通过一个数据源(如:集合、数组),获取一个流

  2- 中间操作:中间操作是个操作链,对数据源的数据进行n次处理,但是在终结操作前,并不会真正执行。

  3- 终止操作:一旦执行终止操作,就执行中间操作链,最终产生结果并结束Stream。

创建Stream

  1、创建 Stream方式一:通过集合

    Java8 中的 Collection 接口被扩展,提供了两个获取流的方法:

      public default Stream<E> stream() : 返回一个顺序流

      public default Stream<E> parallelStream() : 返回一个并行流

  2、创建 Stream方式二:通过数组

    Java8 中的 Arrays 的静态方法 stream() 可以获取数组流:

      public static <T> Stream<T> stream(T[] array): 返回一个流

    还有重载形式,能够处理对应基本类型的数组

  3、创建 Stream方式三:通过 Stream.of()

    可以调用Stream类静态方法 of(), 通过显示值创建一个流。它可以接收任意数量的参数。

      public static<T> Stream<T> of(T... values) : 返回一个顺序流

  4、创建 Stream方式四:创建无限流

    可以使用静态方法 Stream.iterate() 和 Stream.generate(), 创建无限流。

      public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f):返回一个无限流

      public static<T> Stream<T> generate(Supplier<T> s) :返回一个无限流

中间操作

  多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。

方 法 描 述
filter(Predicate p) 筛选,接收 Lambda , 从流中排除某些元素
distinct() 去除,通过流所生成元素的equals() 去除重复元素
limit(long maxSize) 截断流,使其元素不超过给定数量
skip(long n) 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
peek(Consumer action) 接收Lambda,对流中的每个数据执行Lambda体操作
sorted() 产生一个新流,其中按自然顺序排序
sorted(Comparator com) 产生一个新流,其中按比较器顺序排序
map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
mapToDouble(ToDoubleFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream。
mapToInt(ToIntFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream。
mapToLong(ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream。
flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

终结操作

  终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是 void。流进行了终止操作后,不能再次使用。

方法 描述
boolean allMatch(Predicate p) 检查是否匹配所有元素
boolean anyMatch(Predicate p) 检查是否至少匹配一个元素
boolean noneMatch(Predicate p) 检查是否没有匹配所有元素
Optional<T> findFirst() 返回第一个元素
Optional<T> findAny() 返回当前流中的任意元素
long count() 返回流中元素总数
Optional<T> max(Comparator c) 返回流中最大值
Optional<T> min(Comparator c) 返回流中最小值
void forEach(Consumer c) 迭代
T reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 T
U reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 Optional<T>
R collect(Collector c) 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法

  Collector 接口中方法的实现决定了如何对流执行收集的操作(如收集到 List、Set、Map)。另外, Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例。

Optional<T>

  为了解决空指针异常,Optional 提供很多有用的方法,这样我们就不用显式进行空值检测。

  Optional实际上是个容器:它可以保存类型 T 的值,或者仅仅保存 null。

API

  1、如何创建Optional对象?或者说如何用Optional来装值对象或null值

    (1)static <T> Optional<T> empty() :用来创建一个空的Optional

    (2)static <T> Optional<T> of(T value) :用来创建一个非空的Optional

    (3)static <T> Optional<T> ofNullable(T value) :用来创建一个可能是空,也可能非空的Optional

  2、如何从Optional容器中取出所包装的对象呢?

    (1)T get() :要求Optional容器必须非空

        T get()与of(T value)使用是安全的

    (2)T orElse(T other) :

        orElse(T other) 与 ofNullable(T value)配合使用,

        如果Optional容器中非空,就返回所包装值,如果为空,就用orElse(T other)other指定的默认值(备胎)代替

    (3)T orElseGet(Supplier<? extends T> other) :

        如果Optional容器中非空,就返回所包装值,如果为空,就用Supplier接口的Lambda表达式提供的值代替

    (4)<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)

        如果Optional容器中非空,就返回所包装值,如果为空,就抛出你指定的异常类型代替原来的NoSuchElementException

  3、其他方法

    (1)boolean isPresent() :判断Optional容器中的值是否存在

    (2)void ifPresent(Consumer<? super T> consumer) :

        判断Optional容器中的值是否存在,如果存在,就对它进行Consumer指定的操作,如果不存在就不做

    (3)<U> Optional<U> map(Function<? super T,? extends U> mapper)

        判断Optional容器中的值是否存在,如果存在,就对它进行Function接口指定的操作,如果不存在就不做

重要的一点是 Optional 不是 Serializable。因此,它不应该用作类的字段。

Jackson 库支持把 Optional 当作普通对象。也就是说,Jackson 会把空对象看作 null,而有值的对象则把其值看作对应域的值。

Java语法进阶16-Lambda-Stream-Optional的更多相关文章

  1. Java语法进阶13-文件、IO流

    File File是文件和目录路径名的抽象表示形式,即File类是文件或目录的路径,而不是文件本身,因此File类不能直接访问文件内容本身,如果需要访问文件内容本身,则需要使用输入/输出流. File ...

  2. Java基础进阶:内部类lambda重点摘要,详细讲解成员内部类,局部内部类,匿名内部类,Lambda表达式,Lambda表达式和匿名内部类的区别,附重难点,代码实现源码,课堂笔记,课后扩展及答案

    内部类lambda重点摘要 内部类特点: 内部类可以直接访问外部类,包括私有 外部类访问内部类必须创建对象 创建内部对象格式: 外部类.内部类 对象名=new外部类().new内部类(); 静态内部类 ...

  3. Java语法进阶12-集合

    集合 集合:是一种容器,用来装对象的容器,不能装基本数据类型. 数组也是容器,可以用来装基本数据类型,也可以用来装对象. 本质上,集合需要用对应的数据结构实现,是多个类实现接口Collection系列 ...

  4. Java语法进阶10-泛型

    泛型 泛型:参数化的类型,即把数据类型当做参数来传递 有的地方又称为泛化的类型,用一个单个大写字母,例如<T>来代表任意类型,这个T就是泛化的类型. 泛型的好处: (1)表示某个变量的类型 ...

  5. Java语法进阶10-多线程

    多线程 并发与并行.进程,线程调度自行百度 线程(thread):是一个进程中的其中一条执行路径,CPU调度的最基本调度的单位.同一个进程中线程可以共享一些内存(堆.方法区),每一个线程又有自己的独立 ...

  6. Java语法进阶14-网络编程

    网络编程 软件结构 C/S结构 :全称为Client/Server结构,是指客户端和服务器结构. B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构. 网络通信协议 网络通信 ...

  7. Java 函数式编程(Lambda表达式)与Stream API

    1 函数式编程 函数式编程(Functional Programming)是编程范式的一种.最常见的编程范式是命令式编程(Impera Programming),比如面向过程.面向对象编程都属于命令式 ...

  8. 超强的Lambda Stream流操作

    原文:https://www.cnblogs.com/niumoo/p/11880172.html 在使用 Stream 流操作之前你应该先了解 Lambda 相关知识,如果还不了解,可以参考之前文章 ...

  9. Java8 新特性 Lambda & Stream API

    目录 Lambda & Stream API 1 Lambda表达式 1.1 为什么要使用lambda表达式 1.2 Lambda表达式语法 1.3 函数式接口 1.3.1 什么是函数式接口? ...

随机推荐

  1. 给js加版本号解决浏览器缓存问题

    我们知道打开网页时浏览器会加载需要的资源,比如图片.音频.js文件.css文件等.并且会把这些资源作为缓存保存下来,再次打开网页时缓存好的资源就不需要再次加载了.但是,这样有一个问题,就是当程序猿更新 ...

  2. JSONPath-简单入门

    JSONPath - 是xpath在json的应用. xml最大的优点就有大量的工具可以分析,转换,和选择性的提取文档中的数据.XPath是这些最强大的工具之一. 如果可以使用xpath来解析json ...

  3. tab选项卡平滑滚动vue

    <html lang="en"> <head> <meta charset="UTF-8"> <title>Ti ...

  4. 2019-7-29-win10-uwp-如何使用DataTemplate

    title author date CreateTime categories win10 uwp 如何使用DataTemplate lindexi 2019-7-29 10:2:32 +0800 2 ...

  5. 2018-11-13-WPF-禁用实时触摸

    title author date CreateTime categories WPF 禁用实时触摸 lindexi 2018-11-13 10:45:37 +0800 2018-5-4 21:0:3 ...

  6. CodeForces 1204 (#581 div 2)

    传送门 A.BowWow and the Timetable •题意 给你一个二进制数,让你求小于这个数的所有4的幂的个数 •思路 第一反应是二进制与四进制转换 (其实不用真正的转换 QwQ) 由于二 ...

  7. iptables总结,开启端口,查看端口占用情况

    Centos查看端口占用情况和开启端口命令 Centos查看端口占用情况命令,比如查看80端口占用情况使用如下命令: lsof -i tcp:80 列出所有端口 netstat -ntlp mac上查 ...

  8. CachedRowSet 接口

    Sun Microsystems 提供的 CachedRowSet 接口的参考实现是一个标准实现.开发人员可以按原样使用此实现.可以扩展它,也可以选择自己编写此接口的实现. CachedRowSet  ...

  9. There is no Action mapped for namespace [/] and action name [login] associate解决办法 .

    写了一个JSP项目,在配置struts2时遇到了这个错误,在网上逛了一大圈后终于解决了这个问题.具体解决方法是: 1.struts.xml的名字和位置 这里特别提一点,很多人遇到这个错误都是名字错误, ...

  10. python密码输入模块getpass

    import getpass pwd = getpass.getpass("请输入密码") print(pwd)