回答

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; 
} 

本來我沒有Fil的解決方案eExtensionFilter,但注意到我可以通過動態添加過濾來提高效率。節省是指數級的。我從47秒降到700毫秒。

由於FileExtensionFilter將包含Set中所有擴展的重複副本,因此您可以通過消除Set all來清理內存使用情況。

2

沒有更高效的一個。該算法將不得不測試每個文件,如果它的擴展名是一個,這是以前從未見過的。所以最好的算法將具有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; 
} 
+0

通過使用fileNameFilter發現了一個稍微改進的方法 – Randyaa 2012-03-25 07:18:53

+0

它只是隱藏了複雜性。 'FileNameFilter'也必須查看每個文件名。它仍然是'O(n)'。 – 2012-03-25 16:05:05

+0

我同意,但是一旦我添加了過濾器,我就看到了戲劇性的性能提升。也許使用這套設備真的是發生放緩的地方。 – Randyaa 2012-03-26 03:30:47

相關問題