使用Stream流完成按年份对已按时间降序排列的博客内容进行分组
在做自己的博客系统练手项目的时候想到可以做一个时间轴,按年份进行分类,并输出博客的创建时间以及博客标题,那实际上目前也已得知我只需要几个字段:
- 博客Id:用于点击博客标题的时候跳转详情页面
- 博客标题
- 创建时间
那么现在问题来了,我如果要进行根据年份排序,那这个返回的结果肯定是个集合,而这个集合中每一个都有一个年份字段,并且对应的就有一个博客响应参数的集合,有的家人可能就会想到,可以用map解决啊!而事实上,我们也知道HashMap并没有排序的功能,数据量少的时候可能会跟着想要的效果来,而数据量一大就会出问题。再可能会想到用TreeMap等等,确实也不是不行,但是传回到页面上的话我个人觉得还是不要用map的好,还是用不管称VO也罢,DTO也罢,就这么个东西,我在这姑且叫DTO。
综上,我定义的DTO:
@Data
public class ArchiveResDTO implements Serializable {
private static final long serialVersionUID = 6984512812515768639L;
/** 博客所属年份 */
private Integer year;
/** 对应年份下得博客列表 */
private List<BlogArchiveResDTO> blogs;
}
@Data
public class BlogArchiveResDTO implements Serializable {
private static final long serialVersionUID = 8709905582996347365L;
/** 文章Id 便于跳往详情页 */
private Integer id;
/** 文章标题 */
private String title;
/** 创建时间 */
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
}
好了,接下来核心的功能就是要完成几个事情:
- 博客结果按创建日期降序排序
- 博客结果集按年份分组,年份也是按降序排序
- 把博客从博客实体转成响应到页面的DTO
- 剩下一些杂七杂八的就是根据自己的喜好了,比如时间截取只要月日以后的等等
废话不多说了,直接上代码:
List<Blog> blogs = this.blogService.list(queryWrapper);
if (null != blogs && !blogs.isEmpty()) {
// 按年份进行分组
Map<Integer, List<Blog>> blogYearMap = blogs.stream().collect(Collectors.groupingBy(blog -> DateUtil.getYear(blog.getCreateTime())));
resData = blogYearMap.entrySet().stream().map(entry -> {
// 将按年份分组的map转化成List<ArchiveResDTO> ArchiveResDTO : Integer Year; List<BlogArchiveResDTO>
ArchiveResDTO archiveResDTO = new ArchiveResDTO();
archiveResDTO.setYear(entry.getKey());
archiveResDTO.setBlogs(entry.getValue().stream().map(blog -> {
// 将map中每一个blog实体类转成BlogArchiveResDTO
BlogArchiveResDTO blogArchiveResDTO = new BlogArchiveResDTO();
blogArchiveResDTO.setId(blog.getId());
blogArchiveResDTO.setTitle(blog.getTitle());
blogArchiveResDTO.setCreateTime(blog.getCreateTime());
return blogArchiveResDTO;
// 在List<BlogArchiveResDTO>中先对博客进行时间排序
}).sorted(Comparator.comparing(BlogArchiveResDTO::getCreateTime).reversed()).collect(Collectors.toList()));
return archiveResDTO;
// 再对List<ArchiveResDTO>进行年份的排序
}).sorted(Comparator.comparingInt(ArchiveResDTO::getYear).reversed()).collect(Collectors.toList());
由于我这个项目中使用的是MyBatis和MyBatis-plus,前面的逻辑我就不过多展示了,自己可以去筛选想要的条件,比如状态为显示的,当前用户所创建的等等。逻辑上我采取的就是使用两次stream流来完成转化和分组,值得一提的是,建议不要直接使用Date类中的getYear()哦,不然会有惊喜发生的。