0

フォルダ階層を歩き、unqiue拡張子のリストを取得する最も効果的な方法は何ですか?どのようにしてユニークなファイル拡張子を見つけることができますか?

これはthis questionと非常に似ていますが、私はJava内からやりたいとします。

File.isDirectory()をチェックし、すべての子を反復処理し、それぞれに拡張子とisDirectoryをチェックしてから、Setなどのユニークなコレクションを保持するという明白な再帰的な解決策がありますが、もう少し効率的な何か。

答えて

0

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 allを削除することで、もう少しメモリ使用量をクリーンアップすることもできます。

2

より効率的なものはありません。アルゴリズムは、拡張子が1であれば、すべてのファイルをテストする必要があります。これは以前は見られませんでした。したがって、最高のアルゴリズムはO(n)の複雑さを持ちます。

Setにすべてのディレクトリを繰り返し回覧して、すべてのファイルの偽装を投げ捨てるのは私の考えでは可能です。


劇的なパフォーマンスゲイン

は正しく HashMapをuseingないの副作用かもしれ;)私はあなたのメソッドが含まれて使用するのではなく、全体のセットを反復処理することを、ご覧ください。 の場合、元のバージョンのが真であれば、パフォーマンスは疑わしいと私には明らかです。

私はまだ拡張子を抽出し、ちょうどHashSetにそれらを追加することが最もパフォーマンス解決することを期待:カスタムのFileFilter

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

ファイル名フィルタ – Randyaa

+0

を使用して、やや改善されたアプローチを見つけました。複雑さを隠すだけです。 'FileNameFilter'はそれぞれのファイル名をすべて調べなければなりません。まだ 'O(n)'です。 –

+0

私は同意しますが、フィルターを追加すると劇的なパフォーマンスの向上が見られました。おそらくセットで作業しているのは本当にスローダウンが起こっていた場所です。 – Randyaa

関連する問題