Ich möchte eine Liste der Dateien in einem Verzeichnis erhalten, aber ich möchte sie so sortieren, dass die ältesten Dateien an erster Stelle stehen. Meine Lösung bestand darin, File.listFiles aufzurufen und die Liste basierend auf File.lastModified neu zu sortieren, aber ich habe mich gefragt, ob es einen besseren Weg gibt.
Bearbeiten: Meine aktuelle Lösung besteht, wie vorgeschlagen, darin, einen anonymen Komparator zu verwenden:
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());
} });
file.lastModified()
sehr oft an. Holen Sie sich besser alle Daten zuerst und bestellen Sie später, damit dasfile.lastModified()
nur einmal pro Datei aufgerufen wird.Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
Arrays.sort(files, Comparator.comparingLong(File::lastModified));
Antworten:
Ich denke, Ihre Lösung ist der einzig vernünftige Weg. Die einzige Möglichkeit, die Liste der Dateien abzurufen, ist die Verwendung von File.listFiles (). In der Dokumentation wird angegeben, dass dies keine Garantie für die Reihenfolge der zurückgegebenen Dateien gibt. Daher müssen Sie einen Komparator schreiben , der File.lastModified () verwendet, und diesen zusammen mit dem Array von Dateien an Arrays.sort () übergeben .
quelle
Dies kann schneller sein, wenn Sie viele Dateien haben. Hierbei wird das Muster "Dekorieren-Sortieren-Nichtdekorieren" verwendet, sodass das Datum der letzten Änderung jeder Datei nur einmal abgerufen wird und nicht jedes Mal, wenn der Sortieralgorithmus zwei Dateien vergleicht. Dies reduziert möglicherweise die Anzahl der E / A-Aufrufe von O (n log n) auf O (n).
Es ist jedoch mehr Code, daher sollte dieser nur verwendet werden, wenn Sie sich hauptsächlich mit Geschwindigkeit befassen und er in der Praxis messbar schneller ist (was ich nicht überprüft habe).
quelle
Elegante Lösung seit Java 8:
Oder wenn Sie es in absteigender Reihenfolge möchten, kehren Sie es einfach um:
quelle
files.sort(Comparator.comparingLong(File::lastModified));
ArrayList<File> files = new ArrayList<File>(Arrays.asList(directory.listFiles()))
, das ist nicht einfacher als nurFile[] files = directory.listFiles()
.ArrayList<File>(...)
in viniciussss Kommentar benötigt, um eine veränderbare Liste zu erhalten, die sortiert werden kann.) Ich fand diesen Thread auf der Suche nach einer Möglichkeit, eine Liste von Dateien zu sortieren. Also habe ich diesen Code hinzugefügt, damit die Leute ihn einfach kopieren können, wenn sie zufällig auch Listen haben.Comparator
Klasse hat keinen MethodenaufrufcomparingLong
Was ist mit einem ähnlichen Ansatz, aber ohne auf die langen Objekte zu boxen:
quelle
Sie können sich auch Apache Commons IO ansehen. Es verfügt über einen eingebauten zuletzt geänderten Komparator und viele andere nützliche Dienstprogramme für die Arbeit mit Dateien.
quelle
In Java 8:
Arrays.sort(files, (a, b) -> Long.compare(a.lastModified(), b.lastModified()));
quelle
Importe:
Apache Commons
Code:
quelle
Wenn die zu sortierenden Dateien gleichzeitig mit der Sortierung geändert oder aktualisiert werden können:
Java 8+
Java 7
Beide Lösungen erstellen eine temporäre Kartendatenstruktur, um eine konstante letzte Änderungszeit für jede Datei im Verzeichnis zu sparen. Der Grund dafür ist, dass wenn Ihre Dateien während der Sortierung aktualisiert oder geändert werden, Ihr Komparator gegen die Transitivitätsanforderungen des Generalvertrags der Komparatorschnittstelle verstößt, da sich die zuletzt geänderten Zeiten während des Vergleichs möglicherweise ändern.
Wenn Sie andererseits wissen, dass die Dateien während Ihrer Sortierung nicht aktualisiert oder geändert werden, können Sie mit so ziemlich jeder anderen Antwort auf diese Frage davonkommen, von der ich teilweise bin:
Java 8+ (Keine gleichzeitigen Änderungen während des Sortierens)
Hinweis: Ich weiß, dass Sie die Übersetzung von und zu Dateiobjekten im obigen Beispiel vermeiden können, indem Sie Files :: getLastModifiedTime api in der sortierten Stream-Operation verwenden. Dann müssen Sie sich jedoch mit geprüften E / A-Ausnahmen in Ihrem Lambda befassen, was immer schmerzhaft ist . Ich würde sagen, wenn die Leistung kritisch genug ist, dass die Übersetzung nicht akzeptabel ist, würde ich entweder die überprüfte IOException im Lambda behandeln, indem ich sie als UncheckedIOException weitergebe, oder ich würde auf die Datei-API insgesamt verzichten und mich nur mit Dateiobjekten befassen:
quelle
quelle
Wo
listFiles
ist die Sammlung aller Dateien in ArrayListquelle
Sie können versuchen, Guave Bestellung :
quelle
Sie können die Apache LastModifiedFileComparator- Bibliothek verwenden
quelle
quelle
Ich bin zu diesem Beitrag gekommen, als ich nach dem gleichen Problem gesucht habe, aber in
android
. Ich sage nicht, dass dies der beste Weg ist, um sortierte Dateien nach dem Datum der letzten Änderung zu erhalten, aber es ist der einfachste Weg, den ich bisher gefunden habe.Der folgende Code kann für jemanden hilfreich sein.
Vielen Dank
quelle
for
Schleife können Sie sehen, dass ich aufgenommenlist.length-1
habei >=0
, um Sie einfach in umgekehrter Reihenfolge zu iterieren.Es gibt eine sehr einfache und bequeme Möglichkeit, das Problem ohne zusätzlichen Komparator zu lösen. Codieren Sie einfach das Änderungsdatum mit dem Dateinamen in den String, sortieren Sie es und entfernen Sie es später erneut.
Verwenden Sie eine Zeichenfolge mit fester Länge 20, geben Sie das Änderungsdatum (lang) ein und füllen Sie es mit führenden Nullen. Fügen Sie dann einfach den Dateinamen an diese Zeichenfolge an:
Was passiert ist das hier:
Dateiname1: C: \ data \ file1.html Letzte Änderung: 1532914451455 Letzte Änderung 20 Ziffern: 00000001532914451455
Dateiname1: C: \ data \ file2.html Letzte Änderung: 1532918086822 Letzte Änderung 20 Ziffern: 00000001532918086822
wandelt Dateinamen um in:
Dateiname1: 00000001532914451455C: \ data \ file1.html
Dateiname2: 00000001532918086822C: \ data \ file2.html
Sie können diese Liste dann einfach sortieren.
Alles, was Sie tun müssen, ist, die 20 Zeichen später erneut zu entfernen (in Java 8 können Sie sie mit der Funktion .replaceAll für das gesamte Array mit nur einer Zeile entfernen).
quelle
Es gibt auch einen ganz anderen Weg, der vielleicht noch einfacher ist, da wir nicht mit großen Zahlen umgehen.
Anstatt das gesamte Array zu sortieren, nachdem Sie alle Dateinamen und lastModified-Daten abgerufen haben, können Sie einfach jeden einzelnen Dateinamen direkt nach dem Abrufen an der richtigen Position in der Liste einfügen.
Sie können es so machen:
Nachdem Sie Objekt2 zu Position 2 hinzugefügt haben, wird Objekt3 zu Position 3 verschoben.
quelle