java - 重用部分流映射和过滤来组成两个不同的结果

标签 java lambda functional-programming java-8 java-stream

我想知道是否有一种好方法可以重用最终针对不同输出而变化的公共(public)流操作。 下面的示例正是我试图压缩为一步操作的示例:

public static DepartmentInfo extractDepartmentInfo(BaselinePolicy resource) throws ResourceProcessorError {
    Function<Exception, Exception> rpe = e -> new ResourceProcessorError(e.getMessage());
    List<String> parents = 
        Objects.requireNonNull(
            Exceptions.trying(
                () -> Arrays.asList(Exceptions.dangerous(resource::getParentIds).expecting(CMException.class).throwing(rpe))
                            .stream()
                            .map(cId -> Exceptions.dangerous(cId, resource.getCMServer()::getPolicy).expecting(CMException.class).throwing(rpe))
                            .filter(policy -> PagePolicy.class.isAssignableFrom(policy.getClass()))
                            .map(PagePolicy.class::cast)
                            .filter(page -> Exceptions.dangerous(page,
                                                                 p -> Boolean.valueOf(p.getComponentNotNull(ComponentConstants.POLOPOLY_CLIENT, 
                                                                                                            ComponentConstants.IS_HOME_DEPARTMENT,
                                                                                                            Boolean.FALSE.toString())).booleanValue())
                                                      .expecting(CMException.class).throwing(rpe))
                            .map(page -> Exceptions.dangerous(page, p -> p.getExternalId().getExternalId()).expecting(CMException.class).throwing(rpe)), ResourceProcessorError.class)
                            .collect(Collectors.toList()));
    String externalId = parents.get(parents.size()-1).toString();
    List<String> list = 
        Objects.requireNonNull(
            Exceptions.trying(
                () -> Arrays.asList(Exceptions.dangerous(resource::getParentIds).expecting(CMException.class).throwing(rpe))
                            .stream()
                            .map(cId -> Exceptions.dangerous(cId, resource.getCMServer()::getPolicy).expecting(CMException.class).throwing(rpe))
                            .filter(policy -> PagePolicy.class.isAssignableFrom(policy.getClass()))
                            .map(PagePolicy.class::cast)
                            .map(page -> 
                                Exceptions.dangerous(page, 
                                        p -> p.getChildPolicy(PATH_SEGMENT) != null && 
                                             StringUtils.hasLength(SingleValued.class.cast(p.getChildPolicy(PATH_SEGMENT)).getValue())? 
                                             SingleValued.class.cast(p.getChildPolicy(PATH_SEGMENT)).getValue(): p.getName()).expecting(CMException.class).throwing(rpe))
                            .filter(val -> val != null && !val.isEmpty()), ResourceProcessorError.class)
                            .collect(Collectors.toList()));
    if(list.size() > 3) {
        list = list.subList(list.size() - 3, list.size()-1);
    }
    switch(list.size()) {
        case 0: {
            throw new ResourceProcessorError("br.com.oesp.XMLRender.error.noProduct");
        }
        case 1: {
            return DepartmentInfo.withProduct(list.get(0), externalId);
        }
        case 2: {
            return DepartmentInfo.withProduct(list.get(0), externalId).withDepartment(list.get(1));
        }
        default: {
            return DepartmentInfo.withProduct(list.get(0), externalId).withDepartment(list.get(1)).withSubDepartment(list.get(2));
        }
    }
}

请注意,两者都重复第一步:

List<String> parents = 
    Objects.requireNonNull(
        Exceptions.trying(
            () -> Arrays.asList(Exceptions.dangerous(resource::getParentIds).expecting(CMException.class).throwing(rpe))
                        .stream()
                        .map(cId -> Exceptions.dangerous(cId, resource.getCMServer()::getPolicy).expecting(CMException.class).throwing(rpe))
                        .filter(policy -> PagePolicy.class.isAssignableFrom(policy.getClass()))
                        .map(PagePolicy.class::cast)

这不仅是阅读上的问题,而且特别是因为我要重做两次繁重的操作,同时以更命令的方式我会做一次。

最佳答案

您正在尝试做两件事:

  • 避免创建输入数组的冗余工作
  • 避免map/filter/map的冗余代码

第一个很简单:

    List<Id> list = Arrays.asList(Exceptions.dangerous(resource::getParentIds)
                    .expecting(CMException.class)
                    .throwing(rpe));

现在,您可以从该源提取流两次,而无需重新实现它。

下一位只是一个从列表到流的函数:

Function<List<Id>, Stream<Something>> asStream = 
    list -> list.stream().map(...).filter(...).map(...);

现在,只需这样开始您的直播:

asStream.apply(list).moreStuff().moreStuff()

关于java - 重用部分流映射和过滤来组成两个不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31172888/

相关文章:

java - Spring安全异常

functional-programming - Clojure 的惰性如何与对 Java/不纯代码的调用相互作用?

functional-programming - Jan Willem Klop 的 "(L L L...)"Y 组合器如何工作?

c++ - 停止通用 C++14 `curry` 函数递归

java - 通过 JDBC 查询 Oracle DB 给出 null,而直接查询给出输出

java - 防止 Jackson ObjectMapper 自动使用 toString() 格式化复合映射键

c# - 为什么这个 lambda 闭包虽然没有在运行时执行,但会产生垃圾?

python - 将函数应用于 pandas 数据帧的每一列而不使用 for 循环?

java - 有没有办法将现有界面变成功能界面?

java - 查询 FirebaseListAdapter 以仅将特定子项返回到自定义 View