Optional和Stream的组合使用

一、介绍

之间文章提到过,Optional的核心是帮助我们减少空指针异常的出现,它和Stream一起使用时,可以达到 减少空指针异常,又能简化代码 的效果。

二、定义Approve实体

java 复制代码
import lombok.*;

import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Approve {
    private String approveId;
    private List<NodeInfo> nodeList;
    private CreateApprove createInfo;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
class NodeInfo implements Comparable<NodeInfo> {
    private String nodeId;
    private String nodeName;
    private int sort;
    private List<NodeProcessor> nodeProcessorList;

    //按照 sort 进行升序排序
    @Override
    public int compareTo(NodeInfo o) {
        return Integer.compare(getSort(), o.getSort());
    }
}

@Data
@NoArgsConstructor
@AllArgsConstructor
class NodeProcessor {
    private String processorId;
    private String handlerUser;
    private String state;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
class CreateApprove {
    private String creator;
    private LocalDateTime createTime;
}

三、提供创建Approve的工具类

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class ApproveProvider {
    public static List<NodeInfo> buildNodeList() {
        List<NodeInfo> nodeList = new ArrayList<NodeInfo>();
        List<NodeProcessor> nodeProcessorA = new ArrayList<>();
        nodeProcessorA.add(new NodeProcessor("processorId-A1", "处理人小红", "处理完成"));
        nodeProcessorA.add(new NodeProcessor("processorId-A2", "处理人小张", "处理中"));
        nodeProcessorA.add(new NodeProcessor("processorId-A3", "处理人小白", "处理中"));
        // 节点A
        NodeInfo nodeInfoA = new NodeInfo("nodeId-A", "节点A", 0, nodeProcessorA);

        List<NodeProcessor> nodeProcessorB = new ArrayList<>();
        nodeProcessorB.add(new NodeProcessor("processorId-B", "处理人小兰", "处理中"));
        //节点B
        NodeInfo nodeInfoB = new NodeInfo("nodeId-B", "节点B", 7, nodeProcessorB);

        List<NodeProcessor> nodeProcessorC = new ArrayList<>();
        nodeProcessorC.add(new NodeProcessor("processorId-C", "处理人小黑", "未处理"));
        //节点C
        NodeInfo nodeInfoC = new NodeInfo("nodeId-C", "节点C", 5, nodeProcessorC);

        //节点D
        NodeInfo nodeInfoD = new NodeInfo("nodeId-D", "节点D", 2, null);

        nodeList.add(nodeInfoA);
        nodeList.add(nodeInfoB);
        nodeList.add(nodeInfoC);
        nodeList.add(nodeInfoD);
        return nodeList;
    }
}

四、简单Demo

需求一:收集A节点里处理中的数据

需求二:筛选出节点A中状态为"处理中"的数据,并判断处理人是否为小白

需求三:对象中的nodeList数据,按照 sort 进行排序

java 复制代码
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Optional 和 Stream
 */
public class OptionalAndStreamDemo {
    public static void main(String[] args) {
        Approve approveHasNode = new Approve();
        approveHasNode.setNodeList(ApproveProvider.buildNodeList());

        //获取所有节点的处理人信息-1
        List<List<NodeProcessor>> processorList1 = Optional.of(approveHasNode)    //包装顶层对象
                .map(Approve::getNodeList)      //提取节点列表
                .map(Collection::stream)        // Collection::stream 等价于 nodeInfoList -> nodeInfoList.stream()
                .orElse(Stream.empty())         //兜底,就算节点列表为null ,也会返回一个空流,保证流程不会异常
                .map(NodeInfo::getNodeProcessorList)  //提取所有节点的处理人列表
                .collect(Collectors.toList());   //收集结果

        //获取所有节点的处理人信息-2 [扁平化流]
        List<NodeProcessor> processorList2 = Optional.of(approveHasNode)    //包装顶层对象
                .map(Approve::getNodeList)      //提取节点列表
                .map(Collection::stream)        //节点列表nodeList 转 Stream流
                .orElse(Stream.empty())         //兜底,就算节点列表为null ,也返回一个空流
                .map(NodeInfo::getNodeProcessorList)  //提取所有节点的 nodeProcessorList
                .filter(Objects::nonNull)       //过滤,仅保留每个节点下,不为 null的nodeProcessorList
                .flatMap(Collection::stream)    //扁平化流:将所有节点的nodeProcessorList流合并为单个nodeProcessorList流
                .collect(Collectors.toList());  //收集结果

        //需求一:收集A节点里处理中的数据 [扁平化流]
        List<NodeProcessor> processorList3 = Optional.of(approveHasNode)    //包装顶层对象
                .map(Approve::getNodeList)      //提取节点列表
                .map(Collection::stream)        //节点列表NodeList 转 Stream流
                .orElse(Stream.empty())         //兜底,就算节点列表为null ,也返回一个空流
                .filter(nodeInfo -> nodeInfo.getNodeId().equals("nodeId-A")) //过滤,仅保留节点列表中nodeId为 "nodeId-A"的节点
                .map(NodeInfo::getNodeProcessorList)  //因为链式加载的原因,所以肯定是提取节点A下面的数据,而不是提取所有节点
                .filter(Objects::nonNull)       //过滤,仅保留A节点下,不为null的nodeProcessorList
                .flatMap(Collection::stream)    //扁平化流:将节点A的nodeProcessorList流合并为单个nodeProcessorList流
                .filter(processor -> processor.getState().equals("处理中"))
                .collect(Collectors.toList());  //收集结果

        //需求二:筛选出节点A中状态为"处理中"的数据,并判断处理人是否为小白
        boolean result = Optional.of(approveHasNode)    //包装顶层对象
                .map(Approve::getNodeList)      //提取节点列表
                .map(Collection::stream)        //节点列表NodeList 转 Stream流
                .orElse(Stream.empty())         //兜底,就算节点列表为null ,也返回一个空流
                .filter(nodeInfo -> nodeInfo.getNodeId().equals("nodeId-A")) //过滤,仅保留节点列表中nodeId为 "nodeId-A"的节点
                .map(NodeInfo::getNodeProcessorList)  //因为链式加载的原因,所以肯定是提取节点A下面的数据,而不是提取所有节点
                .filter(Objects::nonNull)       //过滤,仅保留A节点下,不为null的nodeProcessorList
                .flatMap(Collection::stream)    //扁平化流:将节点A的nodeProcessorList流合并为单个nodeProcessorList流
                //过滤,仅保留节点A中,处理状态是处理中的NodeProcessor数据
                .filter(processor -> processor.getState().equals("处理中"))
                //过滤出来的NodeProcessor数据,只要包含有一个"处理人小白",就返回true,否则返回false
                .anyMatch(processor -> processor.getHandlerUser().equals("处理人小白"));
        System.out.println("判断结果为:" + result);

        //需求三:对象中的nodeList数据,按照 sort 进行排序
        List<NodeInfo> nodeInfos = Optional.of(approveHasNode)
                .map(Approve::getNodeList)      //提取节点列表
                .map(Collection::stream)        //节点列表NodeList 转 Stream流
                .orElse(Stream.empty())         //兜底,就算节点列表为null ,也返回一个空流
                .sorted(NodeInfo::compareTo)   //升序排序
                .collect(Collectors.toList());
        System.out.println("排序结果为:" + nodeInfos);
    }
}

举个例子,我甚至可以NodeList不传值,这代码也不会出现空指针异常,并且anyMatch方法判断的时候,仍然会返回 false

如果不使用Stream流,肯定要做一堆判断,比如先要判断 nodeList集合是否为空,再判断 nodeProcessorList 集合是否为空,这样才能保证避免空指针,最后才可以添加筛选条件。

相关推荐
heartbeat..6 小时前
Redis 中的锁:核心实现、类型与最佳实践
java·数据库·redis·缓存·并发
6 小时前
java关于内部类
java·开发语言
好好沉淀6 小时前
Java 项目中的 .idea 与 target 文件夹
java·开发语言·intellij-idea
gusijin6 小时前
解决idea启动报错java: OutOfMemoryError: insufficient memory
java·ide·intellij-idea
To Be Clean Coder6 小时前
【Spring源码】createBean如何寻找构造器(二)——单参数构造器的场景
java·后端·spring
吨~吨~吨~6 小时前
解决 IntelliJ IDEA 运行时“命令行过长”问题:使用 JAR
java·ide·intellij-idea
你才是臭弟弟6 小时前
SpringBoot 集成MinIo(根据上传文件.后缀自动归类)
java·spring boot·后端
短剑重铸之日6 小时前
《设计模式》第二篇:单例模式
java·单例模式·设计模式·懒汉式·恶汉式
码农水水6 小时前
得物Java面试被问:消息队列的死信队列和重试机制
java·开发语言·jvm·数据结构·机器学习·面试·职场和发展
summer_du6 小时前
IDEA插件下载缓慢,如何解决?
java·ide·intellij-idea