在blog.html中展示评论时,起初很正常。但是,当楼中楼的评论多起来的时候,有部分评论会重复。
效果如下:
先给解决方法
把原recursively(Comment)方法的 line 6 放到 line 7 的else分支中,如下:
private void recursively(Comment comment) {
tempReplys.add(comment);//顶节点添加到临时存放集合
if (comment.getReplyComments().size() > 0) {
List<Comment> replys = comment.getReplyComments();
for (Comment reply : replys) {
// tempReplys.add(reply);
// if (reply.getReplyComments().size() > 0) {
// recursively(reply);
// }
if (reply.getReplyComments().size() > 0) {
recursively(reply);
} else {
tempReplys.add(reply);
}
}
}
}
我们来分析一下原因:
回到CommentServiceImpl.java
@Override
public List<Comment> listCommentByBlogId(Long blogId) {
Sort sort = Sort.by("createTime");
List<Comment> commentList = commentRepository.findByBlogIdAndParentCommentNull(blogId, sort);
return eachComment(commentList);
}
/**
* 循环每个评论根节点
*/
private List<Comment> eachComment(List<Comment> comments) {
List<Comment> commentsView = new ArrayList<>();
for (Comment comment : comments) {//重新copy一份,防止破坏原查询结果
Comment c = new Comment();
BeanUtils.copyProperties(comment, c);
commentsView.add(c);
}
//合并评论的各层子代到第一级子代集合中
combineChildren(commentsView);
return commentsView;
}
/**
* @param comments root根节点,blog不为空的对象集合
* @return
*/
private void combineChildren(List<Comment> comments) {
for (Comment comment : comments) {
List<Comment> replys1 = comment.getReplyComments();
for (Comment reply1 : replys1) {
//循环迭代,找出子代,存放在tempReplys中
recursively(reply1);
}
//修改顶级节点的reply集合为迭代处理后的集合
comment.setReplyComments(tempReplys);
//清除临时存放区
tempReplys = new ArrayList<>();
}
}
//存放迭代找出的所有子代的集合
private List<Comment> tempReplys = new ArrayList<>();
/**
* 递归迭代,剥洋葱
*
* @param comment 被迭代的对象
* @return
*/
private void recursively(Comment comment) {
tempReplys.add(comment);//顶节点添加到临时存放集合
if (comment.getReplyComments().size() > 0) {
List<Comment> replys = comment.getReplyComments();
for (Comment reply : replys) {
tempReplys.add(reply);
if (reply.getReplyComments().size() > 0) {
recursively(reply);
}
}
}
}
注意观察最后一个函数recursively(Comment),
当遍历到第三层子树(及以上)的时候,
step 1时,子树根节点添加进了tempReplys,
step 2进入递归
step 3时,子树根节点再一次被添加进了tempReplys。
连续添加两次子树根节点,肯定会重复。
这给我们一个启示,写代码的时候,要尽可能多考虑特殊情况~