Java
File Management
Sorting Algorithms
Date Modified
Programming Tips

Best way to list files in Java, sorted by Date Modified?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Sorting files by modification time is a common requirement for log viewers, backup tools, and import jobs. In modern Java, the cleanest solution is to use the java.nio.file API, read file metadata once, and then sort the results with an explicit comparator.

Prefer Path and Files Over File

The old java.io.File API still works, but java.nio.file.Path and Files are usually a better fit. They expose richer metadata, work well with streams, and make error handling more explicit.

If you only need a quick list of entries, Files.list is often enough. The important detail is that the returned stream must be closed, so use try with resources.

java
1import java.io.IOException;
2import java.nio.file.Files;
3import java.nio.file.Path;
4import java.nio.file.Paths;
5
6public class ListFilesBasic {
7    public static void main(String[] args) throws IOException {
8        Path directory = Paths.get("data");
9
10        try (var paths = Files.list(directory)) {
11            paths.forEach(System.out::println);
12        }
13    }
14}

That example lists files, but it does not sort them. The naive next step is to sort with a comparator that calls Files.getLastModifiedTime repeatedly. That works for small directories, but it performs a file attribute lookup every time the comparator runs, which becomes wasteful as the list grows.

Read Attributes Once, Then Sort

A better pattern is to collect each path together with its last modified timestamp, then sort the collected values. This keeps the comparator simple and avoids repeating filesystem work.

java
1import java.io.IOException;
2import java.nio.file.FileTime;
3import java.nio.file.Files;
4import java.nio.file.Path;
5import java.nio.file.Paths;
6import java.util.ArrayList;
7import java.util.Comparator;
8import java.util.List;
9
10public class SortByModifiedTime {
11    private static final class FileEntry {
12        private final Path path;
13        private final FileTime lastModified;
14
15        private FileEntry(Path path, FileTime lastModified) {
16            this.path = path;
17            this.lastModified = lastModified;
18        }
19    }
20
21    public static void main(String[] args) throws IOException {
22        Path directory = Paths.get("data");
23        List<FileEntry> entries = new ArrayList<>();
24
25        try (var paths = Files.list(directory)) {
26            paths.filter(Files::isRegularFile)
27                 .forEach(path -> {
28                     try {
29                         entries.add(new FileEntry(path, Files.getLastModifiedTime(path)));
30                     } catch (IOException e) {
31                         throw new RuntimeException("Failed to read metadata for " + path, e);
32                     }
33                 });
34        }
35
36        entries.sort(
37            Comparator.comparing((FileEntry entry) -> entry.lastModified)
38                      .thenComparing(entry -> entry.path.getFileName().toString())
39        );
40
41        for (FileEntry entry : entries) {
42            System.out.printf("%s  %s%n", entry.lastModified, entry.path.getFileName());
43        }
44    }
45}

This sorts from oldest to newest. If you want the newest files first, reverse the time comparator:

java
1entries.sort(
2    Comparator.comparing((FileEntry entry) -> entry.lastModified).reversed()
3              .thenComparing(entry -> entry.path.getFileName().toString())
4);

The secondary comparison by file name matters more than people expect. If two files have the same timestamp, the sort stays deterministic instead of appearing random across runs.

Choosing the Right Listing Method

Files.list works for one directory level. If you need recursive traversal, use Files.walk. If you are only dealing with a very large directory and want lower overhead, DirectoryStream can also be a good option.

For many applications, the practical approach is:

  • use Files.list for one directory
  • filter out directories unless you explicitly want them
  • read timestamps once
  • sort in memory

If your goal is just "give me the newest file", you can still follow the same pattern, but stop at the maximum entry:

java
1FileEntry newest = entries.stream()
2    .max(Comparator.comparing(entry -> entry.lastModified))
3    .orElseThrow(() -> new IllegalStateException("No files found"));
4
5System.out.println("Newest file: " + newest.path);

That makes the intent clearer than manually tracking a running maximum in a loop.

Common Pitfalls

The most common mistake is using File.listFiles() and assuming the returned order means anything. It does not; the filesystem can return entries in any order.

Another frequent issue is calling Files.getLastModifiedTime inside the comparator. That makes sorting slower and harder to debug because I/O happens during comparison instead of during collection.

It is also easy to forget that Files.list returns a stream backed by operating system resources. If you do not close it, especially in long-running programs, you can leak directory handles.

Finally, decide whether directories should be included. A mixed list of files and folders is valid, but many tasks really want regular files only. Filter explicitly so the behavior matches the requirement.

Summary

  • Prefer java.nio.file.Path and Files for new Java code.
  • Read lastModified metadata once before sorting.
  • Add a secondary sort key such as file name for deterministic output.
  • Use Files.list for one level and Files.walk for recursive traversal.
  • Close directory streams with try with resources to avoid leaking handles.

Course illustration
Course illustration

All Rights Reserved.