Лучший способ перечислить файлы в Java, отсортированные по дате изменения? - PullRequest
224 голосов
/ 15 октября 2008

Я хочу получить список файлов в каталоге, но я хочу отсортировать его так, чтобы самые старые файлы были первыми. Мое решение состояло в том, чтобы вызвать File.listFiles и просто использовать список, основанный на File.lastModified, но мне было интересно, есть ли лучший способ.

Edit: мое текущее решение, как предлагается, заключается в использовании анонимного компаратора:

File[] files = directory.listFiles();

Arrays.sort(files, new Comparator<File>(){
    public int compare(File f1, File f2)
    {
        return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());
    } });

Ответы [ 16 ]

95 голосов
/ 15 октября 2008

Я думаю, что ваше решение - единственный разумный путь. Единственный способ получить список файлов - это использовать File.listFiles () , и в документации говорится, что это не дает никаких гарантий относительно порядка возвращаемых файлов. Поэтому вам нужно написать Comparator , который использует File.lastModified () и передать его вместе с массивом файлов Arrays.sort () .

45 голосов
/ 22 ноября 2010

Это может быть быстрее, если у вас много файлов. При этом используется шаблон decorate-sort-undecorate, чтобы дата последнего изменения каждого файла выбиралась только один раз , а не каждый раз, когда алгоритм сортировки сравнивает два файла. Это потенциально уменьшает количество вызовов ввода / вывода с O (n log n) до O (n).

Тем не менее, это больше код, поэтому его следует использовать только в том случае, если вы в основном озабочены скоростью, и на практике она значительно выше (что я не проверял).

class Pair implements Comparable {
    public long t;
    public File f;

    public Pair(File file) {
        f = file;
        t = file.lastModified();
    }

    public int compareTo(Object o) {
        long u = ((Pair) o).t;
        return t < u ? -1 : t == u ? 0 : 1;
    }
};

// Obtain the array of (file, timestamp) pairs.
File[] files = directory.listFiles();
Pair[] pairs = new Pair[files.length];
for (int i = 0; i < files.length; i++)
    pairs[i] = new Pair(files[i]);

// Sort them by timestamp.
Arrays.sort(pairs);

// Take the sorted pairs and extract only the file part, discarding the timestamp.
for (int i = 0; i < files.length; i++)
    files[i] = pairs[i].f;
33 голосов
/ 03 февраля 2014

А как насчет подобного подхода, но без привязки к объектам Long:

File[] files = directory.listFiles();

Arrays.sort(files, new Comparator<File>() {
    public int compare(File f1, File f2) {
        return Long.compare(f1.lastModified(), f2.lastModified());
    }
});
28 голосов
/ 09 июня 2017

Элегантное решение начиная с Java 8:

File[] files = directory.listFiles();
Arrays.sort(files, Comparator.comparingLong(File::lastModified));

Или, если вы хотите, чтобы это происходило в порядке убывания, просто поменяйте местами:

File[] files = directory.listFiles();
Arrays.sort(files, Comparator.comparingLong(File::lastModified).reversed());
25 голосов
/ 15 октября 2008

Вы также можете посмотреть apache commons IO , он имеет встроенный последний измененный компаратор и множество других полезных утилит для работы с файлами.

14 голосов
/ 05 октября 2015

В Java 8:

Arrays.sort(files, (a, b) -> Long.compare(a.lastModified(), b.lastModified()));

12 голосов
/ 12 августа 2014

Импорт:

org.apache.commons.io.comparator.LastModifiedFileComparator

Apache Commons

Код:

public static void main(String[] args) throws IOException {
        File directory = new File(".");
        // get just files, not directories
        File[] files = directory.listFiles((FileFilter) FileFileFilter.FILE);

        System.out.println("Default order");
        displayFiles(files);

        Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
        System.out.println("\nLast Modified Ascending Order (LASTMODIFIED_COMPARATOR)");
        displayFiles(files);

        Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
        System.out.println("\nLast Modified Descending Order (LASTMODIFIED_REVERSE)");
        displayFiles(files);

    }
5 голосов
/ 13 июля 2013

Если сортируемые файлы можно изменять или обновлять одновременно с сортировкой:


Java 8 +

private static List<Path> listFilesOldestFirst(final String directoryPath) throws IOException {
    try (final Stream<Path> fileStream = Files.list(Paths.get(directoryPath))) {
        return fileStream
            .map(Path::toFile)
            .collect(Collectors.toMap(Function.identity(), File::lastModified))
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByValue())
//            .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))  // replace the previous line with this line if you would prefer files listed newest first
            .map(Map.Entry::getKey)
            .map(File::toPath)  // remove this line if you would rather work with a List<File> instead of List<Path>
            .collect(Collectors.toList());
    }
}

Java 7

private static List<File> listFilesOldestFirst(final String directoryPath) throws IOException {
    final Collection<File> result = Arrays.asList(new File(directoryPath).listFiles());
    final Map<File, Long> constantLastModifiedTimes = new HashMap<File,Long>();
    for (final File f : files) {
        constantLastModifiedTimes.put(f, f.lastModified());
    }
    Collections.sort(files, new Comparator<File>() {
        @Override
        public int compare(final File f1, final File f2) {
            return constantLastModifiedTimes.get(f1).compareTo(constantLastModifiedTimes.get(f2));
        }
    });
    return result;
}


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

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

2 голосов
/ 29 марта 2012
public String[] getDirectoryList(String path) {
    String[] dirListing = null;
    File dir = new File(path);
    dirListing = dir.list();

    Arrays.sort(dirListing, 0, dirListing.length);
    return dirListing;
}
1 голос
/ 30 марта 2018
Collections.sort(listFiles, new Comparator<File>() {
        public int compare(File f1, File f2) {
            return Long.compare(f1.lastModified(), f2.lastModified());
        }
    });

где listFiles - коллекция всех файлов в ArrayList

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