多目录图片获取Groovy代码优化请求:缩减列表提升大文件处理效率
问题描述
场景与用例
- 存储结构:按不同大小分类的文件夹存储图片,每个大小文件夹下包含
CX/MX/VX目录;每个这类目录下有SER00001等系列子目录,图片存放在这些系列子目录中。 - 用例流程:
- 随机选择一个大小分类目录(如5MB、30MB、1GB);
- 该目录下存在
CX/MX/VX类型目录; - 每个类型目录下包含系列子目录;
- 系列子目录内存储图片;
- 按
All/Single规则遍历图片:All:遍历所有CX/MX/VX目录下的所有图片;Single:仅遍历其中一个CX/MX/VX目录下的所有图片。
现有Groovy代码可正常运行,但因定义过多冗余中间列表,处理大量图片时IO与内存开销过大,响应耗时过长,需优化性能。
原代码:
import groovy.io.FileType; def dir = new File(vars.get("dirName")); def selectionPattern = ["All","Single"]; def list = []; def listNew = []; def list_series = []; def list_images = []; def modalityDir = []; def modalityFileName = []; def finalModalityName = []; def rnd = new Random(); def rndSelect = new Random(); def userSelectionForModalityFolder = selectionPattern[rndSelect.nextInt(selectionPattern.size())]; if (userSelectionForModalityFolder === "All") { dir.eachDir() { dirList -> list << dirList } def randomParentDirectorySelected = list[rnd.nextInt(list.size())]; randomParentDirectorySelected.eachDir() { listDir -> list_series << listDir } for (allSelectionDir in list_series) { allSelectionDir.eachDir() { allSelectDirectory -> list_images << allSelectDirectory } } for (int b = 0; b < list_images.size(); b++) { File[] modalityFiles = list_images[b].listFiles(); modalityFileName << modalityFiles } for (int n = 0; n < modalityFileName.size(); n++) { for (int p = 0; p < modalityFileName[n].size(); p++) { finalModalityName << modalityFileName[n][p] } } vars.putObject("All_Modality",finalModalityName); } else { dir.eachDir() { dirList -> list << dirList } def randomParentDirectorySelected = list[rnd.nextInt(list.size())] randomParentDirectorySelected.eachDir() { secDirList -> listNew << secDirList } if (listNew.size() > 2) { def totalFile = ranSelect.nextInt(listNew.size()); } else { Random ranSelect = new Random(); def totalFile = ranSelect.nextInt(listNew.size() + 4); def random_ModalitySelection = listNew[rnd.nextInt(listNew.size())] random_ModalitySelection.eachDir() { modalityD -> modalityDir << modalityD } for (int i = 0; i < modalityDir.size(); i++) { File[] modalityFiles = modalityDir[i].listFiles(); modalityFileName << modalityFiles } for (int j = 0; j < modalityFileName.size(); j++) { for (int k = 0; k < modalityFileName[j].size(); k++) { finalModalityName << modalityFileName[j][k] } } vars.putObject("All_Modality",finalModalityName); } }
优化后的代码
import groovy.io.FileType def dir = new File(vars.get("dirName")) def selectionPattern = ["All", "Single"] def rnd = new Random() def userSelectionForModalityFolder = selectionPattern[rnd.nextInt(selectionPattern.size())] def finalModalityFiles = [] // 1. 筛选并随机选择大小分类目录 def sizeDirs = dir.listFiles().findAll { it.isDirectory() } if (!sizeDirs) { vars.putObject("All_Modality", finalModalityFiles) return } def randomSizeDir = sizeDirs[rnd.nextInt(sizeDirs.size())] // 2. 筛选出CX/MX/VX类型目录 def modalityDirs = randomSizeDir.listFiles().findAll { it.isDirectory() && (it.name in ["CX", "MX", "VX"]) } if (!modalityDirs) { vars.putObject("All_Modality", finalModalityFiles) return } // 3. 根据选择规则确定要遍历的目标目录 def targetModalityDirs = userSelectionForModalityFolder == "All" ? modalityDirs : [modalityDirs[rnd.nextInt(modalityDirs.size())]] // 4. 直接遍历目标目录下的系列子目录,收集所有图片文件 targetModalityDirs.each { modalityDir -> modalityDir.eachDir { seriesDir -> seriesDir.eachFile(FileType.FILES) { imgFile -> finalModalityFiles << imgFile } } } vars.putObject("All_Modality", finalModalityFiles)
优化说明
- 消除冗余中间集合:去掉原代码中
list、listNew等7个不必要的中间列表,直接通过链式筛选与迭代收集最终文件,避免多次集合复制、扩容的内存开销。 - 精准目录过滤:使用
findAll直接筛选出符合要求的大小目录与CX/MX/VX目录,跳过无关目录的遍历,减少IO操作次数。 - 提前边界检查:增加目录为空的判断逻辑,避免后续无意义的遍历操作,快速返回空结果。
- 直接收集文件:使用
eachFile(FileType.FILES)直接遍历系列目录下的文件,无需先收集目录再遍历文件,减少一层嵌套与IO调用。 - 复用实例与简化逻辑:仅创建一个
Random实例,合并All/Single分支的公共逻辑,同时修复原代码中ranSelect未定义就使用的潜在bug。
内容的提问来源于stack exchange,提问作者Jyoti Prakash Mallick
相关产品推荐
相关产品推荐

