如何找到所有独特的文件扩展名在Java中找到文件夹层次结构
问题描述:
什么是漫步文件夹层次结构并获取unqiue扩展名列表的最有效方式?如何找到所有独特的文件扩展名在Java中找到文件夹层次结构
这与this question非常相似,除了我想从Java内部完成。
有一个明显的递归解决方案检查File.isDirectory(),迭代所有孩子,检查每个扩展和isDirectory,然后保持一个唯一的集合(如一个集合),但我试图看看是否有更高效的一点。
答
定制的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;
}
本来我没有Fil的解决方案eExtensionFilter,但注意到我可以通过动态添加过滤来提高效率。节省是指数级的。我从47秒降到700毫秒。
由于FileExtensionFilter将包含Set中所有扩展的重复副本,因此您可以通过消除Set all来清理内存使用情况。
答
没有更高效的一个。该算法将不得不测试每个文件,如果它的扩展名是一个,这是以前从未见过的。所以最好的算法将具有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;
}
通过使用fileNameFilter发现了一个稍微改进的方法 – Randyaa 2012-03-25 07:18:53
它只是隐藏了复杂性。 'FileNameFilter'也必须查看每个文件名。它仍然是'O(n)'。 – 2012-03-25 16:05:05
我同意,但是一旦我添加了过滤器,我就看到了戏剧性的性能提升。也许使用这套设备真的是发生放缓的地方。 – Randyaa 2012-03-26 03:30:47