Java Arrays.sort() Длительное время

Я использую функцию Java Arrays.sort() для сортировки списка файлов по их последнему измененному времени. Сорт для 245 файлов занимает около 5 секунд. Это кажется слишком длинным для меня. Я чувствую, что это не должно занимать более 0,5 секунды. Это хорошее предположение? Что я делаю не так? ИЛИ это нормально?

public static class LastModifiedComparator implements Comparator<File> {
    @Override
    public int compare(File f1, File f2) {
        return (int)(f1.lastModified() - f2.lastModified());
    }       
}

File folder = new File( "C:\\Whatever\\" );
File[] filesInFolder = folder.listFiles();
logger.debug("Starting File Sort");
Arrays.sort(filesInFolder, new LastModifiedComparator());
logger.debug("Done File Sort");

Вывод в журнале

2012-08-10 14:24:20,333 DEBUG http-8080-4 <ClassName>:73 - Starting File Sort
2012-08-10 14:24:25,915 DEBUG http-8080-4 <ClassName>:75 - Done File Sort

Ответы

Ответ 1

Вам нужно будет улучшить логику Comparator. Вам нужно кешировать значения lastModified(), потому что реализация этого метода выполняется довольно медленно. Я предлагаю обернуть экземпляры File в сопоставимый объект вашего создания, который будет кэшировать значение:

public class FileLmWrapper implements Comparable<FileLmWrapper> {
  public final File f;
  public final long lastModified;
  public FileLmWrapper(File f) { 
    this.f = f; 
    lastModified = f.lastModified();
  }
  public int compareTo(FileLmWrapper other) {
    return Long.compare(this.lastModified, other.lastModified);
  }
}

Ответ 2

File.lastModified должен перейти в ОС для запроса, когда файл был последним изменен - ​​он не кэширован. Вы делаете это дважды за сравнение, а Arrays.sort использует mergesort - O(n log n). Включение 245 для n, что около 580 сравнений или 1100 вызовов ОС для получения последнего измененного времени. Это означает, что вы можете получить около 230 последних изменений в секунду. Кажется, что это немного медленнее, но, безусловно, более правдоподобно, чем сравнение в JVM с таким длинным

Как отмечает Marko Topolnik abd NgSan, исправление будет состоять в том, чтобы сначала кэшировать последнее модифицированное время для всех файлов. Я бы сделал это, создав новый объект класса, который объединяет файл и время, а затем сортирует эти объекты. Таким образом, у вас будет только 245 вызовов File.lastModified, и сортировка займет примерно 1/5 раз.

Ответ 3

Я точно не знаю, но кажется, что он делает дисковый ввод-вывод каждый раз, когда вы читаете Модифицированное время - таким образом, медленность. Возможно, быстрее просто получить измененные времена в объекте вместе с объектом File, а затем отсортировать.

Ответ 4

Операция сравнения

@Override
public int compare(File f1, File f2) {
    return (int)(f1.lastModified() - f2.lastModified());
}  

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

Ответ 5

Сортировка, реализованная в java в <удачном > модифицированном Quick Sort настроенном Merge Sort, который будет иметь среднюю сложность времени выполнения O (nlogn). Итак, нам нужно сконцентрироваться на ваших Файловых операциях, таких как получение lastModifiedTime. Вы уверены, что эти файлы являются локальными файлами или общим диском, который занимает латентность сети?