走出文件夹层次结构并获取unqiue扩展名列表的最有效方法是什么?
这与this question非常相似,只是我想在Java中做到这一点。
有一个明显的递归解决方案,检查File.isDirectory(),遍历所有子节点,检查每个子节点上的扩展名和isDirectory,然后保留一个唯一的集合(例如Set),但我试图看看是否有什么东西更有效率。
答案 0 :(得分:2)
效率不高。如果它的扩展名是1,那么算法将必须测试每个文件,这是以前从未见过的。因此,最佳算法的复杂度为O(n)
。
根据我的意见,递归到所有目录并在Set
中抛出所有文件的扩展名是我们能做的最好的。
戏剧性的增益可能是不正确使用HashMap
的副作用;)我看到,您遍历整个集合而不是使用contains方法。如果您在原始版本中那个是真的那么,那对我来说很明显,表现是值得怀疑的。
我仍然希望,提取扩展程序并将它们添加到HashSet
是最高性能的解决方案:
static String[] filenames = { "edit.txt", "my.notes.txt", "sheet.xlxs",
".bash", "README" };
static HashSet<String> exts = new HashSet<>();
public static void main(String[] args) {
// we add every extension to a hashset
for (String filename : filenames) {
exts.add(getExtension(filename));
}
// just dumps the set contents
for (String ext: exts) {
System.out.println(ext);
}
}
private static String getExtension(String filename) {
String ext = "";
// calculate the index only once
int lastIndexOfDot = filename.lastIndexOf('.');
// "README" and ".bash" are files with no extension!
if (lastIndexOfDot > 0) {
exts.add(filename.substring(lastIndexOfDot));
}
return ext;
}
答案 1 :(得分:0)
自定义FileFilter:
public class FileExtensionFilter implements FilenameFilter {
private Set<String> filteredExtensions;
public FileExtensionFilter() {
filteredExtensions = new HashSet<String>();
}
@Override
public boolean accept(File dir, String name) {
boolean accept = true;
for (String filteredExtension:filteredExtensions) {
accept = accept && !name.endsWith(filteredExtension);
}
return accept;
}
public void addFilteredExtension(String extension) {
filteredExtensions.add(extension);
}
}
递归方法解决方案:
public Set<String> checkForExtensions(File file) {
Set<String> extensions = new HashSet<String>();
if (file.isDirectory()) {
for (File f : file.listFiles(fileExtensionFilter)) {
extensions.addAll(checkForExtensions(f));
}
} else {
//NOTE: if you don't want the '.' in the extension you'll need to add a '+1' to the substring call
String extension = file.getName().substring(Math.max(file.getName().lastIndexOf('.'),0));
extensions.add(extension);
fileExtensionFilter.addFilteredExtension(extension);
}
return extensions;
}
最初我有没有FileExtensionFilter的相同解决方案,但注意到我可以通过动态添加到过滤来提高效率。节省是指数级的。我从47秒下降到700毫秒。
由于FileExtensionFilter将包含Set中所有扩展的副本,因此您现在还可以通过消除Set all来清除内存使用量。