Java基础教程(17)-Java8中的lambda表达式和Stream、Optional

简介: 【4月更文挑战第17天】Lambda表达式是Java 8引入的函数式编程特性,允许函数作为参数或返回值。它有简洁的语法:`(parameters) -> expression 或 (parameters) ->{ statements; }`。FunctionalInterface注解用于标记单方法接口,可以用Lambda替换。

lambda表达式

把支持函数式编程的编码风格称为Lambda表达式。
Lambda 表达式,也可称为闭包,

函数式编程

函数是一种最基本的任务,一个大型程序就是一个顶层函数调用若干底层函数,这些被调用的函数又可以调用其他函数,即大任务被一层层拆解并执行。所以函数就是面向过程的程序设计的基本单元。

Java不支持单独定义函数,但可以把静态方法视为独立的函数,把实例方法视为自带 this 参数的函数。

函数式编程就是一种抽象程度很高的编程范式,函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!

Java平台从Java 8开始,支持函数式编程。

lambda 表达式的语法格式如下:

(parameters) -> expression 或 (parameters) ->{ statements; }

lambda 表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
    • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
    • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
    • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值;

只定义了单方法的接口称之为 FunctionalInterface ,用注解 @FunctionalInterface 标记; 从Java 8开始,可以用Lambda表达式替换单方法接口

Stream

Java从8开始,引入了一个全新的流式API:Stream API。它位于 java.util.stream 包中。

Stream代表的是任意Java对象的序列;

Stream API的特点是:

  • Stream API提供了一套新的流式处理的抽象序列;
  • Stream API支持函数式编程和链式操作;
  • Stream可以表示无限序列,并且大多数情况下是惰性求值的

最常用的创建方式有:

  • 1、通过数组来生成 把数组变成 Stream 使用 Arrays.strem() 方法
  • 2、通过集合来生成,直接调用 stream() 方法就可以;

创建 Stream 最简单的方式是直接用 Stream.of() 静态方法,传入可变参数即创建了一个能输出确定元素的 Stream;

应用在Stream流上的操作(Stream的Api),可以分成两种:

  • Intermediate(中间操作): 中间操作的返回结果都是Stream,故可以多个中间操作叠加;
  • Terminal(终止操作): 终止操作用于返回我们最终需要的数据,只能有一个终止操作
中间操作
  1. filter: 过滤流中的某些元素
  2. distinct: 通过流中元素的 hashCode() 和 equals() 去除重复元素
  3. 排序
    sorted():返回由此流的元素组成的流,根据自然顺序排序。
    sorted(Comparator com):返回由该流的元素组成的流,根据提供的 Comparator进行排序。
  4. 截取
    limit(n):返回由此流的元素组成的流,截短长度不能超过 n
    skip(n):在丢弃流的第n元素后,配合limit(n)可实现分页

  5. 转换
    map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
    flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

  6. 消费
    peek:如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值。
    终止操作
  7. 循环:forEach

  8. 计算:min、max、count、sum
    min:返回流中元素最小值
    max:返回流中元素最大值
    count:返回流中元素的总个数
    sum:求和

  9. 匹配:anyMatch、 allMatch、 noneMatch、 findFirst、 findAny
    anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false
    allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false
    noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false
    findFirst:返回流中第一个元素
    findAny:返回流中的任意元素

  10. 收集器:toArray、collect

Optional

Optional类是 Java 8 引入的一个很有趣的特性。它主要解决的问题是空指针异常(NullPointerException)

Optional 类是一个可以为null的容器对象。如果值存在则isPresent(方法会返回true,调用get()方法会返回该对象。

  • Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。
  • Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
  • Optional 类的引入很好的解决空指针异常。
使用Optional对象

Optional类的实例创建有三种方式:

Optional.empty() :创建一个空的 Optional 实例。
Optional.of(T t) :创建一个 Optional 实例,当 t为null时抛出异常(NullPointerException)。
Optional.ofNullable(T t) :创建一个 Optional 实例,但当 t为null时不会抛出异常,而是返回一个空的实例。

Optional实例方法:

  • isPresent():判断optional是否为空,如果空则返回false,否则返回true

  • ifPresent(Consumer c):如果optional不为空,则将optional中的对象传给Comsumer函数

  • orElse(T other):如果optional不为空,则返回optional中的对象;如果为null,则返回 other 这个默认值

  • orElseGet(Supplier other):如果optional不为空,则返回optional中的对象;如果为null,则使用Supplier函数生成默认值other

  • orElseThrow(Supplier exception):如果optional不为空,则返回optional中的对象;如果为null,则抛出Supplier函数生成的异常

  • filter(Predicate p):filter() 接受一个 Predicate 参数,返回测试结果为 true 的值。如果测试结果为 false,会返回一个空的 Optional。

  • map(Function mapper):如果optional不为空,则将optional中的对象 t 映射成另外一个对象 u,并将 u 存放到一个新的optional容器中。

  • flatMap(Function mapper):跟上面一样,在optional不为空的情况下,将对象t映射成另外一个optional

相关文章
|
1天前
|
Java 开发者
Java中的Lambda表达式和函数式接口
在Java 8中,Lambda表达式的引入为Java带来了前所未有的便利性。它允许开发者以更简洁、更高效的方式处理集合、线程等。本文将深入探讨Lambda表达式的概念、用法以及与函数式接口的关系,帮助读者更好地理解和应用这一特性。
|
2天前
|
Java 开发者
探索Java中的Lambda表达式和函数式接口
本文深入探讨了Java 8中引入的Lambda表达式及其与函数式接口的关系,旨在帮助开发者更好地理解这一特性如何简化代码、提高可读性和开发效率。文章首先介绍Lambda表达式的基本概念和语法,然后详细解释函数式接口的定义及其在Java中的应用,最后通过实例展示Lambda表达式在实际编程中的运用。
|
2天前
|
XML Web App开发 Java
《手把手教你》系列技巧篇(七十)-java+ selenium自动化测试-Java中如何读取properties配置文件内容(详解教程)
【6月更文挑战第11天】本文介绍了Java自动化测试中读取properties配置文件的方法。文章首先说明了为何要将配置参数放在properties文件中,然后简述了properties文件的作用和常用的读取方式,包括通过`java.util.Properties`类和`java.util.ResourceBundle`类。接着详细列举了`Properties`类的主要方法,如`getProperty()`、`load()`、`setProperty()`和`store()`等。
12 1
|
3天前
|
存储 Java 测试技术
《手把手教你》系列技巧篇(六十九)-java+ selenium自动化测试 - 读取csv文件(详细教程)
【6月更文挑战第10天】本文介绍了如何在Java中读取CSV文件。首先解释了CSV是逗号分隔值的文本文件,常用于数据交换。接着,在项目实战部分,详细说明了如何通过下载并引入opencsv库来读取CSV文件:包括下载jar包、添加到Eclipse项目、创建CSV文件、编写Java代码读取文件内容,并展示了代码执行后的输出结果。文章以一个简单的代码示例展示了如何使用opencsv读取CSV文件中的数据。
9 0
|
4天前
|
JavaScript 前端开发 Java
蓝易云 - Java现实WebSocket教程
以上就是在Java中实现WebSocket的基本步骤。
5 1
|
5天前
|
安全 Java 编译器
JAVA-多线程知识点总结(二)
JAVA-多线程知识点总结(二)
|
6天前
|
缓存 Java 调度
java面试题之个人对线程池的理解
java面试题之个人对线程池的理解
|
17小时前
|
安全 Java API
Java并发基础-启动和终止线程
Java并发基础-启动和终止线程
6 0
|
5天前
|
Java 调度 数据库
Java中的多线程编程:基础与实践
【6月更文挑战第7天】本文将深入探讨Java中的多线程编程,包括其基本概念、创建方法以及在实际应用中的一些技巧。我们将通过实例来展示如何在Java中有效地使用多线程,以提高程序的性能和响应能力。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解。
|
5天前
|
Java 调度 开发者
Java中的多线程编程:概念与实践
【6月更文挑战第7天】本文深入探讨了Java中多线程编程的核心概念,通过实例演示如何有效利用多线程提升程序性能。文章首先介绍了线程的基本定义及其在Java中的实现方式,随后详细讨论了线程的生命周期、状态转换以及同步机制。最后,通过一个实际案例展示了多线程在解决具体问题中的应用。
11 3