Как я могу найти все уникальные расширения файлов Fin иерархии папок в Java - PullRequest
0 голосов
/ 23 марта 2012

Какой самый эффективный способ пройти иерархию папок и получить список расширений unqiue?

Это очень похоже на этот вопрос , за исключением того, что я хотел бы сделать этоиз Java.

Существует очевидное рекурсивное решение проверки File.isDirectory (), итерации по всем дочерним элементам, проверки расширений и isDirectory для каждого, а затем сохранения уникальной коллекции (такой как Set), но я 'я пытаюсь понять, есть ли что-то более эффективное.

Ответы [ 2 ]

2 голосов
/ 23 марта 2012

Нет более эффективного.Алгоритм должен будет проверить каждый файл, если его расширение равно единице, чего раньше не было.Так что лучший алгоритм будет иметь сложность O(n).

Повторение во всех каталогах и добавление расширений всех файлов в Set - это лучшее, что мы можем сделать, на мой взгляд.


Драматическое усиление может быть побочным эффектом неправильного использования HashMap;) Я вижу, что вы перебираете весь набор вместо использования метода содержимого.Если вы сделали , что в исходной версии верно, тогда мне ясно, что производительность была сомнительной.

Я все еще ожидаю, что извлечение расширений и просто добавление их в 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 голосов
/ 25 марта 2012

Пользовательский 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 миллисекунд.

Теперь вы также можете очистить использование памяти немного больше, удалив Set вместе, так как FileExtensionFilter будет содержать дубликат всех расширений в Set.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...