【Java8新特性】面试官:谈谈Java8中的Stream API有哪些终止操作?

简介: 如果你出去面试,面试官问了你关于Java8 Stream API的一些问题,比如:Java8中创建Stream流有哪几种方式?(可以参见:《【Java8新特性】面试官问我:Java8中创建Stream流有哪几种方式?》)Java8中的Stream API有哪些中间操作?(可以参见:《【Java8新特性】Stream API有哪些中间操作?看完你也可以吊打面试官!!》)如果你都很好的回答了这些问题,那么,面试官可能又会问你:Java8中的Stream API有哪些终止操作呢?没错,这就是Java8中有关Stream API的灵魂三问!不要觉得是面试官在为难你,只有你掌握了这些细节,你就可以反过来

Stream的终止操作

终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、 Integer、Double、String等等,甚至是 void 。

在Java8中,Stream的终止操作可以分为:查找与匹配、规约和收集。接下来,我们就分别简单说明下这些终止操作。

查找与匹配

Stream API中有关查找与匹配的方法如下表所示。

同样的,我们对每个重要的方法进行简单的示例说明,这里,我们首先建立一个Employee类,Employee类的定义如下所示。

@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {
    private static final long serialVersionUID = -9079722457749166858L;
    private String name;
    private Integer age;
    private Double salary;
    private Stauts stauts;
    public enum Stauts{
        WORKING,
        SLEEPING,
        VOCATION
    }
}

接下来,我们在测试类中定义一个用于测试的集合employees,如下所示。

protected List<Employee> employees = Arrays.asList(
    new Employee("张三", 18, 9999.99, Employee.Stauts.SLEEPING),
    new Employee("李四", 38, 5555.55, Employee.Stauts.WORKING),
    new Employee("王五", 60, 6666.66, Employee.Stauts.WORKING),
    new Employee("赵六", 8, 7777.77, Employee.Stauts.SLEEPING),
    new Employee("田七", 58, 3333.33, Employee.Stauts.VOCATION)
);

好了,准备工作就绪了。接下来,我们就开始测试Stream的每个终止方法。

1.allMatch()

allMatch()方法表示检查是否匹配所有元素。其在Stream接口中的定义如下所示。

boolean allMatch(Predicate<? super T> predicate);

我们可以通过类似如下示例来使用allMatch()方法。

boolean match = employees.stream().allMatch((e) -> Employee.Stauts.SLEEPING.equals(e.getStauts()));
System.out.println(match);

注意:使用allMatch()方法时,只有所有的元素都匹配条件时,allMatch()方法才会返回true。

2.anyMatch()方法

anyMatch方法表示检查是否至少匹配一个元素。其在Stream接口中的定义如下所示。

boolean anyMatch(Predicate<? super T> predicate);

我们可以通过类似如下示例来使用anyMatch()方法。

boolean match = employees.stream().anyMatch((e) -> Employee.Stauts.SLEEPING.equals(e.getStauts()));
System.out.println(match);

注意:使用anyMatch()方法时,只要有任意一个元素符合条件,anyMatch()方法就会返回true。

3.noneMatch()方法

noneMatch()方法表示检查是否没有匹配所有元素。其在Stream接口中的定义如下所示。

boolean noneMatch(Predicate<? super T> predicate);

我们可以通过类似如下示例来使用noneMatch()方法。

boolean match = employees.stream().noneMatch((e) -> Employee.Stauts.SLEEPING.equals(e.getStauts()));
System.out.println(match);

注意:使用noneMatch()方法时,只有所有的元素都不符合条件时,noneMatch()方法才会返回true。

4.findFirst()方法

findFirst()方法表示返回第一个元素。其在Stream接口中的定义如下所示。

Optional<T> findFirst();

我们可以通过类似如下示例来使用findFirst()方法。

Optional<Employee> op = employees.stream().sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())).findFirst();
System.out.println(op.get());

5.findAny()方法

findAny()方法表示返回当前流中的任意元素。其在Stream接口中的定义如下所示。

Optional<T> findAny();

我们可以通过类似如下示例来使用findAny()方法。

Optional<Employee> op = employees.stream().filter((e) -> Employee.Stauts.WORKING.equals(e.getStauts())).findFirst();
System.out.println(op.get());

6.count()方法

count()方法表示返回流中元素总数。其在Stream接口中的定义如下所示。

long count();

我们可以通过类似如下示例来使用count()方法。

long count = employees.stream().count();
System.out.println(count);

7.max()方法

max()方法表示返回流中最大值。其在Stream接口中的定义如下所示。

Optional<T> max(Comparator<? super T> comparator);

我们可以通过类似如下示例来使用max()方法。

Optional<Employee> op = employees.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(op.get());

8.min()方法

min()方法表示返回流中最小值。其在Stream接口中的定义如下所示。

Optional<T> min(Comparator<? super T> comparator);

我们可以通过类似如下示例来使用min()方法。

Optional<Double> op = employees.stream().map(Employee::getSalary).min(Double::compare);
System.out.println(op.get());

9.forEach()方法

forEach()方法表示内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反, Stream API 使用内部迭代)。其在Stream接口内部的定义如下所示。

void forEach(Consumer<? super T> action);

我们可以通过类似如下示例来使用forEach()方法。

employees.stream().forEach(System.out::println);

规约

Stream API中有关规约的方法如下表所示。

微信图片_20211118181011.jpg

reduce()方法在Stream接口中的定义如下所示。

T reduce(T identity, BinaryOperator<T> accumulator);
Optional<T> reduce(BinaryOperator<T> accumulator);
<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);

我们可以通过类似如下示例来使用reduce方法。

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream().reduce(0, (x, y) -> x + y);
System.out.println(sum);
System.out.println("----------------------------------------");
Optional<Double> op = employees.stream().map(Employee::getSalary).reduce(Double::sum);
System.out.println(op.get());

我们也可以搜索employees列表中“张”出现的次数。

Optional<Integer> sum = employees.stream()
   .map(Employee::getName)
   .flatMap(TestStreamAPI1::filterCharacter)
   .map((ch) -> {
    if(ch.equals('六'))
     return 1;
    else
     return 0;
   }).reduce(Integer::sum);
  System.out.println(sum.get());

注意:上述例子使用了硬编码的方式来累加某个具体值,大家在实际工作中再优化代码。

收集

微信图片_20211118181020.jpg

collect()方法在Stream接口中的定义如下所示。

<R> R collect(Supplier<R> supplier,
              BiConsumer<R, ? super T> accumulator,
              BiConsumer<R, R> combiner);
<R, A> R collect(Collector<? super T, A, R> collector);

我们可以通过类似如下示例来使用collect方法。

Optional<Double> max = employees.stream()
   .map(Employee::getSalary)
   .collect(Collectors.maxBy(Double::compare));
  System.out.println(max.get());
  Optional<Employee> op = employees.stream()
   .collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
  System.out.println(op.get());
  Double sum = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));
  System.out.println(sum);
  Double avg = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));
  System.out.println(avg);
  Long count = employees.stream().collect(Collectors.counting());
  System.out.println(count);
  System.out.println("--------------------------------------------");
  DoubleSummaryStatistics dss = employees.stream()
   .collect(Collectors.summarizingDouble(Employee::getSalary));
  System.out.println(dss.getMax());

如何收集Stream流?

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

微信图片_20211118181028.jpg

每个方法对应的使用示例如下表所示。

微信图片_20211118181051.jpg

public void test4(){
    Optional<Double> max = emps.stream()
        .map(Employee::getSalary)
        .collect(Collectors.maxBy(Double::compare));
    System.out.println(max.get());
    Optional<Employee> op = emps.stream()
        .collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
    System.out.println(op.get());
    Double sum = emps.stream()
        .collect(Collectors.summingDouble(Employee::getSalary));
    System.out.println(sum);
    Double avg = emps.stream()
        .collect(Collecors.averagingDouble(Employee::getSalary));
    System.out.println(avg);
    Long count = emps.stream()
        .collect(Collectors.counting());
    DoubleSummaryStatistics dss = emps.stream()
        .collect(Collectors.summarizingDouble(Employee::getSalary));
    System.out.println(dss.getMax());
相关文章
|
11月前
|
Java API 数据处理
Java新特性:使用Stream API重构你的数据处理
Java新特性:使用Stream API重构你的数据处理
Java API 开发者
394 0
|
并行计算 Java API
Java List 集合结合 Java 17 新特性与现代开发实践的深度解析及实战指南 Java List 集合
本文深入解析Java 17中List集合的现代用法,结合函数式编程、Stream API、密封类、模式匹配等新特性,通过实操案例讲解数据处理、并行计算、响应式编程等场景下的高级应用,帮助开发者提升集合操作效率与代码质量。
555 1
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
1081 1
|
缓存 安全 Java
Java 并发新特性实战教程之核心特性详解与项目实战
本教程深入解析Java 8至Java 19并发编程新特性,涵盖CompletableFuture异步编程、StampedLock读写锁、Flow API响应式流、VarHandle内存访问及结构化并发等核心技术。结合电商订单处理、缓存系统、实时数据流、高性能计数器与用户资料聚合等实战案例,帮助开发者高效构建高并发、低延迟、易维护的Java应用。适合中高级Java开发者提升并发编程能力。
629 0
|
安全 Java API
Java 17 及以上版本核心特性在现代开发实践中的深度应用与高效实践方法 Java 开发实践
本项目以“学生成绩管理系统”为例,深入实践Java 17+核心特性与现代开发技术。采用Spring Boot 3.1、WebFlux、R2DBC等构建响应式应用,结合Record类、模式匹配、Stream优化等新特性提升代码质量。涵盖容器化部署(Docker)、自动化测试、性能优化及安全加固,全面展示Java最新技术在实际项目中的应用,助力开发者掌握现代化Java开发方法。
513 1
|
IDE Java API
Java 17 新特性与微服务开发的实操指南
本内容涵盖Java 11至Java 17最新特性实战,包括var关键字、字符串增强、模块化系统、Stream API、异步编程、密封类等,并提供图书管理系统实战项目,帮助开发者掌握现代Java开发技巧与工具。
752 0
|
Java 数据库连接 API
Java 8 + 特性及 Spring Boot 与 Hibernate 等最新技术的实操内容详解
本内容涵盖Java 8+核心语法、Spring Boot与Hibernate实操,按考试考点分类整理,含技术详解与代码示例,助力掌握最新Java技术与应用。
367 2