如何在java中查找文件夹层次结构中的所有唯一文件扩展名

时间:2012-03-23 05:15:53

标签: java file-extension directory-structure

走出文件夹层次结构并获取unqiue扩展名列表的最有效方法是什么?

这与this question非常相似,只是我想在Java中做到这一点。

有一个明显的递归解决方案,检查File.isDirectory(),遍历所有子节点,检查每个子节点上的扩展名和isDirectory,然后保留一个唯一的集合(例如Set),但我试图看看是否有什么东西更有效率。

2 个答案:

答案 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来清除内存使用量。