我想获取目录中的文件列表,但我想对其进行排序,使得最旧的文件是第一个.我的解决方案是调用File.listFiles,然后根据File.lastModified求助于列表,但我想知道是否有更好的方法.
编辑:我建议的当前解决方案是使用匿名比较器:
File[] files = directory.listFiles(); Arrays.sort(files, new Comparator(){ public int compare(File f1, File f2) { return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); } });
Dan Dyer.. 96
我认为你的解决方案是唯一明智的方法.获取文件列表的唯一方法是使用File.listFiles(),文档声明这不保证返回的文件的顺序.因此,您需要编写一个使用File.lastModified()的Comparator,并将其与文件数组一起传递给Arrays.sort().
我认为你的解决方案是唯一明智的方法.获取文件列表的唯一方法是使用File.listFiles(),文档声明这不保证返回的文件的顺序.因此,您需要编写一个使用File.lastModified()的Comparator,并将其与文件数组一起传递给Arrays.sort().
如果您有许多文件,这可能会更快.这使用了decorate-sort-undecorate模式,这样每个文件的最后修改日期只被提取一次,而不是每次排序算法比较两个文件.这可能会减少从O(n log n)到O(n)的I/O调用次数.
但是,这是更多的代码,所以只有在你主要关注速度时它才会被使用,并且在实践中它的速度要快得多(我还没有检查过).
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;
什么是类似的方法,但没有拳击到Long对象:
File[] files = directory.listFiles(); Arrays.sort(files, new Comparator() { public int compare(File f1, File f2) { return Long.compare(f1.lastModified(), f2.lastModified()); } });
File[] files = directory.listFiles(); Arrays.sort(files, Comparator.comparingLong(File::lastModified));
或者,如果您想按降序排列,只需将其反转:
File[] files = directory.listFiles(); Arrays.sort(files, Comparator.comparingLong(File::lastModified).reversed());
你也可以看看apache commons IO,它有一个内置的最后修改过的比较器和许多其他很好的工具来处理文件.
在Java 8中:
Arrays.sort(files, (a, b) -> Long.compare(a.lastModified(), b.lastModified()));
进口:
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); }
private static ListlistFilesOldestFirst(final String directoryPath) throws IOException { try (final Stream 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 instead of List .collect(Collectors.toList()); } }
private static ListlistFilesOldestFirst(final String directoryPath) throws IOException { final List files = Arrays.asList(new File(directoryPath).listFiles()); final Map constantLastModifiedTimes = new HashMap (); for (final File f : files) { constantLastModifiedTimes.put(f, f.lastModified()); } Collections.sort(files, new Comparator () { @Override public int compare(final File f1, final File f2) { return constantLastModifiedTimes.get(f1).compareTo(constantLastModifiedTimes.get(f2)); } }); return files; }
这两种解决方案都创建了一个临时的地图数据结构,以便为目录中的每个文件保存一个不变的上次修改时间.我们需要这样做的原因是,如果在执行排序时更新或修改了文件,那么比较器将违反比较器接口的一般合同的传递性要求,因为在比较期间最后修改的时间可能会发生变化.
另一方面,如果你知道在排序过程中不会更新或修改文件,你可以放弃提交给这个问题的任何其他答案.