传统用递归,先查出所有顶级父节点,再循环调用 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());
}
我这种方式
- 易于理解,双层 for 循环比递归好理解点吧,利用集合的特性。
- 代码简洁,配合 Java8 Stream 流 + lambda 表达式,简介易懂。
- 在完整树的结构中,时间复杂度相同。双层for循环的 n^2 + 过滤子节点的 n。
欢迎评论留言写出你的想法。我们一起交流~
每一次成长,都想与你分享。(小声BB,抽奖用的公众号。)