什麼是漫步文件夾層次結構並獲取unqiue擴展名列表的最有效方式?如何找到所有獨特的文件擴展名在Java中找到文件夾層次結構
這與this question非常相似,除了我想從Java內部完成。
有一個明顯的遞歸解決方案檢查File.isDirectory(),迭代所有孩子,檢查每個擴展和isDirectory,然後保持一個唯一的集合(如一個集合),但我試圖看看是否有更高效的一點。
什麼是漫步文件夾層次結構並獲取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