Java8新特性——Stream API的终止操作

简介: Java8新特性——Stream API的终止操作

文章目录:


1.写在前面

2.终止操作

2.1 终止操作之查找与匹配

2.2 终止操作之归约与收集

1.写在前面


承接了上一篇文章(说完了Stream API的创建方式及中间操作):Stream API的创建方式及中间操作

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

2.终止操作


终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:ListInteger,甚至是 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)
    );
    @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接口中方法的实现决定了如何对流执行收集操作 (如收集到 ListSetMap) 。但是 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字段的映射,然后转为 ListSetHashSet(使用 Collectors 实用类中的静态方法即可完成)。


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

    @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));
    }

相关文章
|
7天前
|
存储 Java API
Java Stream API:现代数据处理之道
Java Stream API:现代数据处理之道
169 92
|
7天前
|
存储 Java API
Java Stream API:现代数据处理之道
Java Stream API:现代数据处理之道
124 68
|
2月前
|
Oracle Java 关系型数据库
掌握Java Stream API:高效集合处理的利器
掌握Java Stream API:高效集合处理的利器
327 80
|
2月前
|
安全 Java API
Java 8 Stream API:高效集合处理的利器
Java 8 Stream API:高效集合处理的利器
216 83
|
12天前
|
监控 算法 API
电商API接口对接实录:淘宝优惠券接口对接处理促销监控系统
在电商开发中,淘宝详情页的“券后价计算”是极易出错的环节。本文作者结合实战经验,分享了因忽略满减券门槛、有效期、适用范围等导致的踩坑经历,并提供了完整的解决方案,包括淘宝API签名生成、券后价计算逻辑、常见坑点及优化建议,助力开发者精准实现券后价功能,避免业务损失。
|
7天前
|
JSON API 数据安全/隐私保护
深度分析淘宝卖家订单详情API接口,用json返回数据
淘宝卖家订单详情API(taobao.trade.fullinfo.get)是淘宝开放平台提供的重要接口,用于获取单个订单的完整信息,包括订单状态、买家信息、商品明细、支付与物流信息等,支撑订单管理、ERP对接及售后处理。需通过appkey、appsecret和session认证,并遵守调用频率与数据权限限制。本文详解其使用方法并附Python调用示例。
|
9天前
|
JSON API 数据格式
淘宝/天猫图片搜索API接口,json返回数据。
淘宝/天猫平台虽未开放直接的图片搜索API,但可通过阿里妈妈淘宝联盟或天猫开放平台接口实现类似功能。本文提供基于淘宝联盟的图片关联商品搜索Curl示例及JSON响应说明,适用于已获权限的开发者。如需更高精度搜索,可选用阿里云视觉智能API。
|
20天前
|
JSON 算法 API
淘宝商品评论API接口核心解析,json数据返回
淘宝商品评论API是淘宝开放平台提供的数据服务接口,允许开发者通过编程方式获取指定商品的用户评价数据,包括文字、图片、视频评论及评分等。其核心价值在于:
|
27天前
|
域名解析 JSON API
【干货满满】如何处理requests库调用API接口时的异常情况
在调用 API 时,网络波动、服务器错误、参数异常等情况难以避免。本文提供一套系统化的异常处理方案,涵盖 requests 库常见异常类型、处理策略、实战代码与最佳实践,通过分类处理、重试机制与兜底策略,提升接口调用的稳定性与可靠性。