怎么用易理解的方式实现树状图?

809 阅读2分钟

传统用递归,先查出所有顶级父节点,再循环调用 getChild(),在 getChild() 中递归调用 getChild()。

这种方式我觉得不太好理解,复杂度详细为 n + n(所有的孩子节点个数),第一个 n 为查出所有父节点的执行次数,n(父节点个数 + 所有的孩子节点个数)表示每次都会从集合中判断是否有子节点。如果集合中是一个完整的树结构,那么父节点个数 + 所有孩子节点个数 = n,即计算次数为 n^2 + n,大O表示法为 O(n^2)

我是这么做的,双层 for 循环匹配子节点,再过滤掉集合中所有子节点。代码如下:

@Data
public class CommentTreeRespDto implements Serializable {

    private static final long serialVersionUID = 9098462797193334657L;

    @ApiModelProperty(value = "评论父id,顶级父id为00000-00000-00000-00000")
    private String parentId;

    @ApiModelProperty(value = "当前日志评论的id")
    private String id;

    @ApiModelProperty(value = "评论内容")
    private String content;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createdDate;

    @ApiModelProperty(value = "评论人")
    private String createdBy;

    @ApiModelProperty(value = "当前评论下的子评论")
    private List<CommentTreeRespDto> childCommentList;
}
    public List<CommentTreeRespDto> getComment(IdBean<String> id) {
        List<CommentTreeRespDto> comment = queryDao.executeForObjectList("selDiaComByDiaId", id);
        comment.forEach(c -> {
            comment.forEach(m -> {
                if (c.getId().equals(m.getParentId())) {
                    if (!CollectionUtils.isEmpty(c.getChildCommentList())) {
                        c.getChildCommentList().add(m);
                    } else {
                        List<CommentTreeRespDto> cs = Lists.newArrayList();
                        cs.add(m);
                        c.setChildCommentList(cs);
                    }
                }
            });
        });

        return comment.stream()
                .filter(e->(e.getParentId().equals(PARENT_ID)))
                .collect(Collectors.toList());
    }

我这种方式

  1. 易于理解,双层 for 循环比递归好理解点吧,利用集合的特性。
  2. 代码简洁,配合 Java8 Stream 流 + lambda 表达式,简介易懂。
  3. 在完整树的结构中,时间复杂度相同。双层for循环的 n^2 + 过滤子节点的 n。

欢迎评论留言写出你的想法。我们一起交流~


每一次成长,都想与你分享。(小声BB,抽奖用的公众号。)