在一长串文件中查找最近修改的3个文件

我有一个文件列表,我想排序和提取前3个最后修改。

约束:由于下游应用程序的兼容性问题,我无法使用Java 7

我目前的选择

解决方案1

File[] files = directory.listFiles(); Arrays.sort(files, new Comparator(){ public int compare(File f1, File f2) { return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); } }); 

解决方案2

 public static void sortFilesDesc(File[] files) { Arrays.sort(files, new Comparator() { public int compare(Object o1, Object o2) { if ((File)o1).lastModified().compareTo((File)o2).lastModified()) { return -1; } else if (((File) o1).lastModified() < ((File) o2).lastModified()) { return +1; } else { return 0; } } }); } 

问题

上述两种解决方案需要更多时间来执行和存储。 我的文件列表包含大约300个tar文件,每个文件大小为200MB。 所以它消耗更多的时间和内存。

有没有办法有效地处理这个?

每个比较操作都使用一个高内存的文件对象有没有办法释放内存并有效地处理它?

你可以更快地做到这一点。

Arrays.sort(…)使用“快速排序”,它需要~n * ln(n)次操作。

这个例子只需要通过整个数组进行一次迭代,这就是操作。

 public static void sortFilesDesc(File[] files) { File firstMostRecent = null; File secondMostRecent = null; File thirdMostRecent = null; for (File file : files) { if ((firstMostRecent == null) || (firstMostRecent.lastModified() < file.lastModified())) { thirdMostRecent = secondMostRecent; secondMostRecent = firstMostRecent; firstMostRecent = file; } else if ((secondMostRecent == null) || (secondMostRecent.lastModified() < file.lastModified())) { thirdMostRecent = secondMostRecent; secondMostRecent = file; } else if ((thirdMostRecent == null) || (thirdMostRecent.lastModified() < file.lastModified())) { thirdMostRecent = file; } } } 

在少量文件上你看不出太大差异,但即使是数十个文件,差异也会很大,对于更大的数字 - 戏剧性。

检查算法的代码(请输入正确的文件结构):

 package com.hk.basicjava.clasload.tests2; import java.io.File; import java.util.Date; class MyFile extends File { private long time = 0; public MyFile(String name, long timeMills) { super(name); time = timeMills; } @Override public long lastModified() { return time; } } public class Files { /** * @param args */ public static void main(String[] args) { File[] files = new File[5]; files[0] = new MyFile("File1", new Date(2013,1,15, 7,0).getTime()); files[1] = new MyFile("File2", new Date(2013,1,15, 7,40).getTime()); files[2] = new MyFile("File3", new Date(2013,1,15, 5,0).getTime()); files[3] = new MyFile("File4", new Date(2013,1,15, 10,0).getTime()); files[4] = new MyFile("File5", new Date(2013,1,15, 4,0).getTime()); sortFilesDesc(files); } public static void sortFilesDesc(File[] files) { File firstMostRecent = null; File secondMostRecent = null; File thirdMostRecent = null; for (File file : files) { if ((firstMostRecent == null) || (firstMostRecent.lastModified() < file.lastModified())) { thirdMostRecent = secondMostRecent; secondMostRecent = firstMostRecent; firstMostRecent = file; } else if ((secondMostRecent == null) || (secondMostRecent.lastModified() < file.lastModified())) { thirdMostRecent = secondMostRecent; secondMostRecent = file; } else if ((thirdMostRecent == null) || (thirdMostRecent.lastModified() < file.lastModified())) { thirdMostRecent = file; } } System.out.println("firstMostRecent : " + firstMostRecent.getName()); System.out.println("secondMostRecent : " + secondMostRecent.getName()); System.out.println("thirdMostRecent : " + thirdMostRecent.getName()); } } 

你必须检查每个文件的lastModified,你不能改变它。 你不需要做的就是排序所有元素只是为了获得前3名。如果你可以使用Guava,你可以使用Ordering.greatestOf (它使用一个好的算法):

 Ordering ordering = Ordering.from( new Comparator(){ public int compare(File f1, File f2) { return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); }); List max3 = ordering.greatestOf(Arrays.asList(directory.listFiles()), 3); 

我是解决方案1,有一些改进

 Arrays.sort(files, new Comparator() { public int compare(File f1, File f2) { long d1 = f1.lastModified(); long d2 = f2.lastModified(); return d1 > d2 ? 1 : d1 < d2 ? -1 : 0; } }); 

避免因Long.valueOf(long)而创建不必要的对象。

File不保存/读取任何文件数据,只保存文件路径,没有性能/内存问题。 这里唯一耗时的操作是从文件系统读取无法避免的修改时间。

您的问题是检索上次修改日期是一项相对昂贵的操作,因为它涉及操作系统逻辑。 因此,如果您不介意获取最新的最新值,则可以将文件包装在类似的类中。

 public class LastModifiedFile implements Comparable { private final File file; private final Date lastModified; public LastModifiedFile(File file) { this.file = file; lastModified = file.lastModified(); } public int compareTo(LastModifiedFile other) { return lastModified.compareTo(other.lastModified); } } 

请注意,在排序期间更改上次修改日期将导致许多排序算法的未定义行为。 如果最后修改日期发生变化,Java 7s Tim Sort实现将抛出exception,因此比较会产生不同的值。