Se i file che stai ordinando possono essere modificati o aggiornati contemporaneamente, l'ordinamento viene eseguito:
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 List<File> files = 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 files;
}
Entrambe queste soluzioni creano una struttura di dati della mappa temporanea per salvare un tempo di ultima modifica costante per ogni file nella directory. La ragione per cui dobbiamo fare questo è che se i tuoi file vengono aggiornati o modificati mentre il tuo ordinamento viene eseguito, il tuo comparatore violerà i requisiti di transitività del contratto generale dell'interfaccia del comparatore perché gli ultimi tempi modificati potrebbero cambiare durante il confronto.
Se, d'altra parte, sai che i file non verranno aggiornati o modificati durante il tuo ordinamento, puoi scappare praticamente con qualsiasi altra risposta inviata a questa domanda, di cui sono parziale a:
Java 8+ (nessuna modifica simultanea durante l'ordinamento)
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)
.sorted(Comparator.comparing(File::lastModified))
.map(File::toPath) // remove this line if you would rather work with a List<File> instead of List<Path>
.collect(Collectors.toList());
}
}
Nota: so che puoi evitare la traduzione da e verso gli oggetti File nell'esempio precedente usando Files :: getLastModifiedTime api nell'operazione di flusso ordinata, tuttavia, devi affrontare le eccezioni IO verificate all'interno della tua lambda che è sempre una seccatura . Direi che se le prestazioni sono abbastanza critiche da rendere inaccettabile la traduzione, allora mi occuperei della IOException selezionata nella lambda propagandola come UncheckedIOException o rinuncerei del tutto all'API Files e gestirò solo gli oggetti File:
final List<File> sorted = Arrays.asList(new File(directoryPathString).listFiles());
sorted.sort(Comparator.comparing(File::lastModified));