大家好,我是程序员牛肉。
最近在爆改我的网盘项目,其中有一个优化点困扰了我很多天:在网盘项目中会有很多需要查询文件树的地方。
比如说用户想要移动当前文件的时候,我们就需要把当前用户的文件夹树查询出来。
我最开始的写法可谓是一点脑子都不动了,直接递归就完事了!
本图片来自网络
在这里贴一下最开始的写法:
private void collectAllSubFolderFileIds(List<String> fileIds, String userId, String parentId, Integer deletionFlag) {
fileIds.add(parentId);
FileInfoQuery query = new FileInfoQuery();
query.setUserId(userId);
query.setFilePid(parentId);
query.setDelFlag(deletionFlag);
query.setFolderType(FileFolderTypeEnums.FOLDER.getType());
List<FileInfo> fileInfos = this.fileInfoMapper.selectList(query);
for (FileInfo fileInfo : fileInfos) {
collectAllSubFolderFileIds(fileIds, userId, fileInfo.getFileId(), deletionFlag);
}
}
可是这种写法的问题实在是太大了,每一次递归都要查询一次数据库,在查询高层次深度的文件数的时候,还可能会有溢出的风险。
一开始我总想着在递归上怎么优化。说实话,确实是有点难想。
可就在一个下午我在蹲厕所的时候,顿悟了。
我们还是不要用递归的手法分批查询文件来构建文件树了。直接一次性把一个文件下的所有文件都查出来,自己手动构建文件树。
基于这个思想其实设计起来就简单了很多。我先说代码逻辑,再谈代码实现。
首先我们从数据库中查到当前这个用户的所有文件夹。
查询出来之后,按照文件夹的父文件夹id进行分类,得到一个HashMap。键是父文件夹id。值是对应的文件夹。
最后我们开始遍历之前的所有文件夹。将当前文件夹的id当作key传入HashMap中,得到的对应值就是这个文件夹的子文件夹集合。
通过这种方式,我们就是实现了非递归查询当前用户的文件树。而为了代码简洁,我使用了大量的Stream流操作,因此看起来会比较绕。
private List<FolderTreeNodeVO> sassembleFolderTreeNodeVOList(List<RPanUserFile> folderRecords) {
if (CollectionUtils.isEmpty(folderRecords)) {
return Lists.newArrayList();
}
List<FolderTreeNodeVO> mappedFolderTreeNodeVOList = folderRecords.stream().map(fileConverter::rPanUserFile2FolderTreeNodeVO).collect(Collectors.toList());
Map<Long, List<FolderTreeNodeVO>> mappedFolderTreeNodeVOMap = mappedFolderTreeNodeVOList.stream().collect(Collectors.groupingBy(FolderTreeNodeVO::getParentId));
for (FolderTreeNodeVO node : mappedFolderTreeNodeVOList) {
List<FolderTreeNodeVO> children = mappedFolderTreeNodeVOMap.get(node.getId());
if (CollectionUtils.isNotEmpty(children)) {
node.getChildren().addAll(children);
}
}
return mappedFolderTreeNodeVOList.stream().filter(node -> Objects.equals(node.getParentId(), FileConstants.TOP_PARENT_ID)).collect(Collectors.toList());
}
但是这种方式也有自己的缺点:他只能够构建当前用户所有文件的文件树。并没有办法从局部开始查找。
所以在一些情况下我们还是要使用递归。比如在重命名一个文件夹的时候,要检查当前文件夹下的子目录有没有重名的情况。
所以我的思路还是有很大的不足的。不知道大家对于这种优化递归来讲,有什么解决方案呢?
关于“HashMap替代递归查询当前用户文件树”的介绍就到这里了。希望我的文章可以帮到你。
你们有什么更好的解决方法吗?