深入理解Java8新特性之Stream API的终止操作步骤

目录
  • 1.写在前面
  • 2.终止操作
    • 2.1 终止操作之查找与匹配
    • 2.2 终止操作之归约与收集

1.写在前面

承接了上一篇文章(说完了Stream API的创建方式及中间操作):深入理解Java8新特性之Stream API的创建方式和中间操作步骤。

我们都知道Stream API完成的操作是需要三步的:创建Stream → 中间操作 → 终止操作。那么这篇文章就来说一下终止操作。

2.终止操作

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

2.1 终止操作之查找与匹配

首先,我们仍然需要一个自定义的Employee类,以及一个存储它的List集合。

在Employee类定义了枚举(BUSY:忙碌;FREE:空闲;VOCATION:休假)

package com.szh.java8;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 *
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee2 {

    private Integer id;
    private String name;
    private Integer age;
    private Double salary;
    private Status status;

    public Employee2(Integer id) {
        this.id = id;
    }

    public Employee2(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public enum Status {
        FREE,
        BUSY,
        VOCATION
    }

}
    List<Employee2> employees = Arrays.asList(
            new Employee2(1001,"张三",26,6666.66, Employee2.Status.BUSY),
            new Employee2(1002,"李四",50,1111.11,Employee2.Status.FREE),
            new Employee2(1003,"王五",18,9999.99,Employee2.Status.VOCATION),
            new Employee2(1004,"赵六",35,8888.88,Employee2.Status.BUSY),
            new Employee2(1005,"田七一",44,3333.33,Employee2.Status.FREE),
            new Employee2(1005,"田七二",44,3333.33,Employee2.Status.VOCATION),
            new Employee2(1005,"田七七",44,3333.33,Employee2.Status.BUSY)
    );

查找所有的员工是否都处于BUSY状态、至少有一个员工处于FREE状态、没有员工处于VOCATION状态。

    @Test
    public void test1() {
        boolean b1 = employees.stream()
                .allMatch((e) -> e.getStatus().equals(Employee2.Status.BUSY));
        System.out.println(b1);

        boolean b2 = employees.stream()
                .anyMatch((e) -> e.getStatus().equals(Employee2.Status.FREE));
        System.out.println(b2);

        boolean b3 = employees.stream()
                .noneMatch((e) -> e.getStatus().equals(Employee2.Status.VOCATION));
        System.out.println(b3);
    }

对员工薪资进行排序之后,返回第一个员工的信息; 筛选出BUSY状态员工之后,返回任意一个处于BUSY状态的员工信息。

    @Test
    public void test2() {
        Optional<Employee2> op1 = employees.stream()
                .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
                .findFirst();
        System.out.println(op1.get());

        System.out.println("----------------------------------");

        Optional<Employee2> op2 = employees.stream()
                .filter((e) -> e.getStatus().equals(Employee2.Status.BUSY))
                .findAny();
        System.out.println(op2.get());
    }

下面,我们来看一下另外一组查找与匹配的方法。

计算处于VOCATION状态的员工数量;对员工薪资字段进行映射,同时获取其中的最高薪资;获取年龄最小的员工信息。

    @Test
    public void test3() {
        long count = employees.stream()
                .filter((e) -> e.getStatus().equals(Employee2.Status.VOCATION))
                .count();
        System.out.println(count);

        Optional<Double> op1 = employees.stream()
                .map(Employee2::getSalary)
                .max(Double::compare);
        System.out.println(op1.get());

        Optional<Employee2> op2 = employees.stream()
                .min((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
        System.out.println(op2.get());
    }

在这里,大家需要注意的一点就是:当前Stream流一旦进行了终止操作,就不能再次使用了。

我们看下面的代码案例。(异常信息说的是:stream流已经被关闭了)

    @Test
    public void test4() {
        Stream<Employee2> stream = employees.stream()
                .filter((e) -> e.getStatus().equals(Employee2.Status.BUSY));
        long count = stream.count();

        stream.map(Employee2::getName);
    }

2.2 终止操作之归约与收集

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

计算整数1~10的和;对员工薪资字段进行映射,之后获取所有员工的薪资总和。

    @Test
    public void test1() {
        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> optional = employees.stream()
                .map(Employee2::getSalary)
                .reduce(Double::sum);
        System.out.println(optional.get());
    }

依次对我们先前定义好的存储员工信息的List集合 做name字段的映射,然后 转为 List、Set、HashSet(使用 Collectors 实用类中的静态方法即可完成)。

在Set、HashSet集合中,由于元素是无序、不可重复的,所以只有一个田七二。

    @Test
    public void test2() {
        List<String> list = employees.stream()
                .map(Employee2::getName)
                .collect(Collectors.toList());
        list.forEach(System.out::println);

        System.out.println("-------------------------------");

        Set<String> set = employees.stream()
                .map(Employee2::getName)
                .collect(Collectors.toSet());
        set.forEach(System.out::println);

        System.out.println("-------------------------------");

        HashSet<String> hashSet = employees.stream()
                .map(Employee2::getName)
                .collect(Collectors.toCollection(HashSet::new));
        hashSet.forEach(System.out::println);
    }

对员工薪资字段做映射,之后通过比较器获取最高薪资;

不做映射处理,直接通过比较器获取薪资最低的员工信息;

计算所有员工的薪资总和;

计算所有员工的平均薪资;

计算员工总数;

对员工薪资字段做映射,之后通过比较器获取最高薪资;

    @Test
    public void test3() {
        Optional<Double> max = employees.stream()
                .map(Employee2::getSalary)
                .collect(Collectors.maxBy(Double::compare));
        System.out.println(max.get());

        Optional<Employee2> min = employees.stream()
                .collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println(min.get());

        Double sum = employees.stream()
                .collect(Collectors.summingDouble(Employee2::getSalary));
        System.out.println(sum);

        Double avg = employees.stream()
                .collect(Collectors.averagingDouble(Employee2::getSalary));
        System.out.println(avg);

        Long count = employees.stream()
                .collect(Collectors.counting());
        System.out.println(count);

        DoubleSummaryStatistics dss = employees.stream()
                .collect(Collectors.summarizingDouble(Employee2::getSalary));
        System.out.println(dss.getMax());
    }

单个条件分组:根据员工状态对Stream流进行分组。 因为分组之后得到的是一个Map集合,key就是员工状态,value则是一个List集合。

    @Test
    public void test4() {
        Map<Employee2.Status, List<Employee2>> map = employees.stream()
                .collect(Collectors.groupingBy(Employee2::getStatus));

        Set<Map.Entry<Employee2.Status, List<Employee2>>> set = map.entrySet();
        Iterator<Map.Entry<Employee2.Status, List<Employee2>>> iterator = set.iterator();
        while (iterator.hasNext()) {
            Map.Entry<Employee2.Status, List<Employee2>> entry = iterator.next();
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        }
    }

多个条件分组:先按照员工状态分组,如果状态相同,再按照员工年龄分组。

    @Test
    public void test5() {
        Map<Employee2.Status, Map<String, List<Employee2>>> map = employees.stream()
                .collect(Collectors.groupingBy(Employee2::getStatus, Collectors.groupingBy((e) -> {
                    if (e.getAge() <= 35) {
                        return "成年";
                    } else if (e.getAge() <= 60) {
                        return "中年";
                    } else {
                        return "老年";
                    }
                })));

        Set<Employee2.Status> set = map.keySet();
        Iterator<Employee2.Status> iterator = set.iterator();
        while (iterator.hasNext()) {
            Employee2.Status next = iterator.next();
            Map<String, List<Employee2>> listMap = map.get(next);
            System.out.println(next);
            System.out.println(listMap);
        }
    }

根据特定的条件对员工进行分区处理。(员工薪资大于等于5000为 true 分区;否则都为 false 分区)。

    @Test
    public void test6() {
        Map<Boolean, List<Employee2>> map = employees.stream()
                .collect(Collectors.partitioningBy((e) -> e.getSalary() >= 5000));
        map.forEach((key,value) -> System.out.println("键:" + key + ", 值:" + value));
    }

以上就是深入理解Java8新特性之Stream API的终止操作步骤的详细内容,更多关于Java8 Stream API 终止操作的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java8中Lambda表达式使用和Stream API详解

    前言 Java8 的新特性:Lambda表达式.强大的 Stream API.全新时间日期 API.ConcurrentHashMap.MetaSpace.总得来说,Java8 的新特性使 Java 的运行速度更快.代码更少.便于并行.最大化减少空指针异常. 0x00. 前置数据 private List<People> peoples = null; @BeforeEach void before () { peoples = new ArrayList<>(); peoples

  • 一文带你掌握Java8强大的StreamAPI

    目录 Stream 概述 Stream 实例化 1.方式一:通过集合 2.方式二:通过数组 3.方式三:通过Stream的of() 4.方式四:创建无限流 Stream 中间操作 1.筛选与切片 2.映射 3.排序 Stream 终止操作 1.匹配与查找 2.归约 3.收集 Stream 概述 Stream API ( java.util.stream) 把真正的函数式编程风格引入到Java中.这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程

  • java8使用Stream API方法总结

    Stream是java8中处理集合的关键抽象概念,它可以指定您希望对集合进行的操作,可以执行非常复杂的查找.过滤和映射数据等操作.使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询. Stream 的三个操作步骤 1.创建Stream. 得到Stream流的第一种方式: 可以通过Collection系列集合提供提供的Stream()或parallelStream @Test public void test1() { //可以通过Collection系列集合提供提供的

  • Java 8中Stream API的这些奇技淫巧!你Get了吗?

    上次老师跟大家分享了 cookie.session和token,今天给大家分享一下Java 8中的Stream API. Stream简介 1.Java 8引入了全新的Stream API.这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同. 2.stream是对集合对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作,或者大批量数据操作. 3.只要给出需要对其包含的元素执行什么操作,比如 "过滤掉长度大于 10 的字符串".&

  • 深入理解Java8新特性之Stream API的创建方式和中间操作步骤

    目录 1.什么是StreamAPI? 2.Stream API操作的三个步骤 2.1 创建Stream 2.2 中间操作 2.2.1 中间操作之筛选与切片 2.2.2 中间操作之映射 2.2.3 中间操作之排序 1.什么是StreamAPI? Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 m Stream API (java.util.stream.*) . Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复

  • Java8新特性之Stream API详解

    一.前言 StreamAPI在Java8版本中使用,关注的是对数据的筛选.查找.存储等 它可以做的事情有:过滤.排序.映射.归约 二.使用流程 Stream实例化中间操作(过滤.排序.映射.规约)终止操作(匹配查找.归约.收集) 三.案例演示 public class EmployeeData { public static List<Employee> getEmployees(){ List<Employee> list = new ArrayList<>(); l

  • 深入理解Java8新特性之Stream API的终止操作步骤

    目录 1.写在前面 2.终止操作 2.1 终止操作之查找与匹配 2.2 终止操作之归约与收集 1.写在前面 承接了上一篇文章(说完了Stream API的创建方式及中间操作):深入理解Java8新特性之Stream API的创建方式和中间操作步骤. 我们都知道Stream API完成的操作是需要三步的:创建Stream → 中间操作 → 终止操作.那么这篇文章就来说一下终止操作. 2.终止操作 终端操作会从流的流水线生成结果.其结果可以是任何不是流的值,例如:List.Integer,甚至是 v

  • 熟练掌握Java8新特性之Stream API的全面应用

    1.写在前面 关于Stream API的内容,已经基本上说完了.大家可以参考我的这两篇文章: 深入理解Java8新特性之Stream API的创建方式和中间操作步骤.深入理解Java8新特性之Stream API的终止操作步骤 那么这篇文章主要就是说一个Stream API的简单应用练习题. 2.应用举例 首先,我们需要创建一个交易员类.交易类.存储这两个类对象的List集合. package com.szh.java8.exer; import lombok.AllArgsConstructo

  • 深入理解Java8新特性之新日期时间API的应用

    目录 1.新旧对比(线程安全问题) 2.LocalDate 3.LocalTime 4.LocalDateTime 5.Instant 6.Duration.Period 7.TestTemporalAdjuster.TestTemporalAdjusters 8.DateTimeFormatter 1.新旧对比(线程安全问题) 我们先来看下面的代码:

  • 深入理解Java8新特性之Lambda表达式的基本语法和自定义函数式接口

    1.写在前面 目前我们学习Java主要用到的应该就是Java8了,或者说大部分企业当前使用的也是Java8.那么既然Java8的应用如此之广泛,一定有一些亮点所在: Lambda 表达式 函数式接口 方法引用与构造器引用 Stream API 接口中的默认方法与静态方法 新时间日期API 其他新特性 速度更快.代码更少(增加了新的语法 Lambda 表达式).强大的 Stream API.便于并行.最大化减少空指针异常 Optional. 2.为什么要使用Lambda表达式? Lambda 是一

  • java8新特性之stream的collect实战教程

    1.list转换成list 不带return方式 List<Long> ids=wrongTmpList.stream().map(c->c.getId()).collect(Collectors.toList()); 带return方式 // spu集合转化成spubo集合//java8的新特性 List<SpuBo> spuBos=spuList.stream().map(spu -> { SpuBo spuBo = new SpuBo(); BeanUtils.c

  • 详解Java8 新特性之日期API

    Java 8 在包java.time下包含了一组全新的时间日期API.下面的例子展示了这组新API里最重要的一些部分: 1.Clock 时钟 Clock类提供了访问当前日期和时间的方法,Clock是时区敏感的,可以用来取代 System.currentTimeMillis() 来获取当前的微秒数.某一个特定的时间点也可以使用Instant类来表示,Instant类也可以用来创建老的java.util.Date对象. Clock clock = Clock.systemDefaultZone();

  • java8新特性之stream流中reduce()求和知识总结

    1.stream().reduce()单字段求和 (1)普通数字求和 public static void test2(){ List<Integer> list= Arrays.asList(new Integer[]{1,2,3,4,5,6,7,8,9}); Integer sum=list.stream().reduce((x,y)->x+y).get(); System.out.println(sum); } 2.BigDecimal求和 public static void m

  • 深入理解Java8新特性之Optional容器类的应用

    1.Optional容器类 Optional<T> 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念.并且可以避免空指针异常. 常用方法 : Optional.of(T t) : 创建一个 Optional 实例 Optional.empty() : 创建一个空的 Optional 实例 Optional.ofNullable(T t) : 若 t 不为 null,创建 Opti

随机推荐