账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    Java8 stream流操作重构递归代码
    39
    0

    原代码:

     private static JSONArray produceTree(List<Resource> resources,boolean needPermission){
        JSONArray tree = new JSONArray();
        if(resources!=null&&resources.size()>Number.ZERO) {//递归退出条件判断
            for (Resource resource : resources) {
                List<Resource> resourceList=resourceService.queryChildTreeByPid(resource.getId());//根据父id查询子资源列表
                JSONArray children = produceTree(resourceList,needPermission,staffName,roleId);//递归,一直向下查找
                JSONObject node=TreeUtil.spellTree(resource);//转换为具体的树形式
                if(children!=null&&children.size()>Number.ZERO){
                    node.put("children",children);
                }else if(needPermission){//需要该资源下对应的权限信息(最后一级,判断下面有没有权限关系)
                    node=toPermission(resource.getId(),node,staffName);
                }
                tree.add(node);
            }
        }
        return tree;
    }
    
    

    Resource结构如下:

            @Data
            public class Resource {
            private Integer id;//资源id
        
            private String resourceName;//资源名称
        
            private String url;//资源地址 可能无用
        
            private String icon;//资源图标
        
            private String clue;// 树形结构横向线索
        
            private Integer distance; // 到根节点的距离 纵向线索
        
            private Integer parentId;// 父资源id
        
            private String description; //资源描述
        
            private Date createtime;//创建时间
        
            private Integer state;// 0未删除 1已删除
            
            List<Resource> children;
        
        }
    

    现在想用java8 Stream流重写这段代码,大概是这样:

            private static List<Resource> recursive(List<Resource> resources){
                return resources.stream()
                        .map(Resource::getId)//第一步转换为id
                        .map(parentId->resourceService.queryChildTreeByPid(parentId))//第二步查找id下对应的资源(id相当于parentId使用)
                        .map(child->Optional.ofNullable(child).filter(obj -> true).ifPresent(isExists->recursive(isExists)))//第三步 如果childrenList不为null,递归此方法
                        .toArray(childrenL->reReousce.setChildren());//第四步 将得到的List<Resource> 收集到上一个resource的children中 , resource.setChildren(childrenList)
            }
    
    

    第三步以后 编译出错
    设想一下 第三步应该用toArray方法收集子资源 然后第四步将收集到的子资源放进对应的父资源resource中 请问如何实现呢

    --------------感谢imanguo大佬的指点 还有某me姓大佬的指点 分享下我的树形结构生产源码-------
    --------------Any library suggestions/code samples/guidance would be greatly appreciated...--------------

    private static ResourceService resourceService;
    private static PermissionService permissionService;
    
    @Autowired
    public TreeUtil(ResourceService resourceService,PermissionService permissionService){
        this.resourceService=resourceService;
        this.permissionService=permissionService;
    }
    /**
     * @Author: zms
     * @Description: 生成菜单树结构
     *
     * clue是线索 例如 1-2-3 代表 根节点是1 1下面有2节点 2下面有3节点
     * 根据收集根节点id 作为线索 可以去除持久化数据里面重复的资源
     * 例如 同时有了 1节点 2节点 因为1是2的父节点 那么有了1就不需要2的存在了 有父节点就拥有其所有子节点
     *
     * @Date: Create on  2018/11/12 14:59
     */
    public static List<Resource> produceTree(List<Resource> resources,boolean needPermission){
        Map<Boolean,List<Resource>> listMap=partitionResource(resources);
        List<Resource> nodeTree=listMap.get(true);//根节点资源树
        List<Resource> duplicateChildTree=listMap.get(false);//非根节点
        String clue=nodeTree.stream().map(Resource::getId).map(String::valueOf).collect(joining("-","","-"));//根节点线索
        List<Resource> childTree=duplicateChildTree.stream().filter(resource -> !clue.contains(resource.getClue())).collect(toList());//去除重复资源
        nodeTree.addAll(childTree);//合并所有
        List<Resource> downTree=TreeUtil.recursiveDown(nodeTree,needPermission);//向下递归查找子节点
        List<Resource> upTree=TreeUtil.recursiveUp(downTree);//向上递归查找父节点
        return merge(upTree);
    }
    /**
     * @Author: zms
     * @Description: 新递归生成树方法 上至下
     *
     *                   5 ---
     *            2 ---  6 ---
     *       1--- 3 ---  7 ---
     *            4 ---  8 ---
     *                   9 ---
     *
     *  以1开始查找到2,3,4 然后2,3,4再次递归 2(5,6) 3(7) 4(8,9)  括号内是对应的children
     *  为什么引入ResourceGroup? 将resource和ChildrenResource 向上抽象一层
     *  Resource中含有其他属性 ResourceGroup仅仅表示父子节点的关系 可以不使用 看个人习惯
     * @Date: Create on  2018/11/8 11:30
     */
    public static List<Resource> recursiveDown(List<Resource> resources, boolean needPermission){
        return resources
                .parallelStream()
                .map(resource -> TreeUtil.toResourceGroup(resource,needPermission))
                .peek(ResourceGroup::autoSet)
                .map(ResourceGroup::getParent)
                .collect(Collectors.toList());
    }
    /**
     * @Author: zms
     * @Description: 转换成resouceGroup收集
     * @Date: Create on  2018/11/8 11:30
     */
    private static ResourceGroup toResourceGroup(Resource resource, boolean needPermission) {
        ResourceGroup resourceGroup=new ResourceGroup();
        resourceGroup.setParent(resource);
        List<Resource> children = findChildren(resource.getId(),needPermission);
        if(Objects.equals(0,children.size())&&needPermission){
            List<Permission> permissions=permissionService.getPermissionByResourceId(resource.getId());
            resourceGroup.setPermissions(permissions);
            return resourceGroup;
        }
        resourceGroup.setChildren(children);
        return resourceGroup;
    }
    /**
     * @Author: zms
     * @Description: 获取父节点对应的子资源
     * @Date: Create on  2018/11/8 11:30
     */
    private static List<Resource> findChildren(Integer parentId,boolean needPermission){
        List<Resource> chidren=resourceService.queryChildTreeByPid(parentId);
        recursiveDown(chidren,needPermission);
        return chidren;
    }
    /**
     * @Author: zms
     * @Description: 新递归生成树方法 下至上
     * @Date: Create on  2018/11/8 18:32
     */
    private static List<Resource> recursiveUp(List<Resource> resources){
        return resources.stream()
                        .map(TreeUtil::toResource)
                        .map(ResourceGroup::getParent)
                        .collect(Collectors.toList());
    }
    
    /**
     *@Author: zms
     *@Description: 递归查找父节点
     *@Date: Create On 2018/11/10 14:33
     */
    private static ResourceGroup toResource(Resource resource){
        ResourceGroup resourceGroup=new ResourceGroup();
        Resource parent=findParent(resource);
        resourceGroup.setParent(parent);
        return resourceGroup;
    }
    /**
     * @Author: zms
     * @Description: 获取收集好的子资源的父节点
     * @Date: Create on  2018/11/8 18:37
     */
    private static Resource findParent(Resource resource){
        if(Objects.equals(0,resource.getParentId())){
            return resource;
        }
        Resource parent=resourceService.getResourceById(resource.getParentId());
        List<Resource> children=new ArrayList<>();
        children.add(resource);
        parent.setChildren(children);
        return recursiveUp(Collections.singletonList(parent)).stream().filter(Objects::nonNull).findFirst().orElse(resource);
    }
    /**
     * @Author: zms
     * @Description:
     *
     *  业务背景: 假设id为1的资源节点下有 2,3,4 三个子资源  可能某个角色只有 2,3的资源树
     *  2 -->1
     *  dulipcate
     *  3 -->1
     *  这时需要把2 3 合并到 1 下
     * @Date: Create on  2018/11/12 11:44
     */
    private static List<Resource> merge(List<Resource> duplicateTree){
        return duplicateTree
                .stream()
                .collect(toMap(Resource::getId, Function.identity(),TreeUtil::mergeChildResource))
                .entrySet()
                .stream()
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());
    }
    
    /**
     * @Author: zms
     * @Description:
     *
     *  id:1                     id:1                      id:1
     *  children:[               children:[                children:[
     *          {                        {                         {
     *              id=2                    id=3    合并为            id=2
     *          }                        }                         },
     *  ]                        ]                                 {
     *                                                               id=3
     *                                                             }
     *
     * @Date: Create on  2018/11/12 12:00
     */
    private static Resource mergeChildResource(Resource resource1,Resource resource2){
        resource1.getChildren().add(resource2.getChildren().get(0));
        return resource1;
    }
    
    /**
     * @Author: zms
     * @Description: 根节点与不是根节点的resource分组
     * @Date: Create on  2018/11/12 15:01
     */
    private static Map<Boolean,List<Resource>> partitionResource(List<Resource> resources){
        return resources.stream().collect(partitioningBy(resource-> Objects.equals(0,resource.getParentId())));
    }
    /**
     * @Author: zms
     * @Description: 去重方法
     * @Date: Create on  2018/8/10 10:13
     */
    
    public static String removeDuplicateString(String str){
        return Stream.of(str.split(",")).distinct().collect(Collectors.joining(","));
    }
    0
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 在Java 8中,我们可以使用Stream API来简化递归代码。以下是一个使用Stream API重构递归代码的例子:

      ```java import java.util.List; import java.util.stream.Collectors;

      public class Main { public static void main(String[] args) { List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); List doubledNumbers = numbers.stream() .map(n -> n * 2) .collect(Collectors.toList()); System.out.println(doubledNumbers); // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] } } ```

      在这个例子中,我们首先创建了一个包含1到10的列表。然后,我们使用Stream API的map方法来将列表中的每个元素都乘以2。最后,我们使用collect方法将结果收集到一个新的列表中。这个新的列表就是我们原始列表的加倍版本。

      这种方法不仅可以简化代码,而且还可以避免在递归过程中出现大量的重复计算。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部