我正在使用Java的Arrays.sort()
函数按照上次修改时间对文件列表进行排序。 245个文件的排序大约需要5秒钟。这对我来说似乎太长了。我觉得它不应该超过0.5秒。这是一个很好的假设吗?我究竟做错了什么?或者这听起来不正常吗?
public static class LastModifiedComparator implements Comparator<File> {
@Override
public int compare(File f1, File f2) {
return (int)(f1.lastModified() - f2.lastModified());
}
}
File folder = new File( "C:\\Whatever\\" );
File[] filesInFolder = folder.listFiles();
logger.debug("Starting File Sort");
Arrays.sort(filesInFolder, new LastModifiedComparator());
logger.debug("Done File Sort");
日志输出
2012-08-10 14:24:20,333 DEBUG http-8080-4 <ClassName>:73 - Starting File Sort
2012-08-10 14:24:25,915 DEBUG http-8080-4 <ClassName>:75 - Done File Sort
答案 0 :(得分:22)
File.lastModified
必须到操作系统查询上次修改文件的时间 - 它没有被缓存。你每次比较都要做两次,Arrays.sort使用mergesort - O(n log n)
。为n
插入245,这是大约580次比较,或1100次调用操作系统以获得最后修改时间。这意味着您每秒可以获得大约230个最后修改过的调用。这看起来似乎有点慢,但肯定比采用那么长的内部JVM比较更合理
正如Marko Topolnik abd NgSan指出的那样,修复方法是首先缓存所有文件的最后修改时间。我会通过创建一个结合了File和那个时间的新类对象,然后对这些对象进行排序来实现。这样,您只需要拨打245次File.lastModified
次电话,排序时间大约为1/5。
答案 1 :(得分:22)
您需要改进Comparator
逻辑。您需要缓存 lastModified()
值,因为该方法的实现速度非常慢。我建议将File
个实例包装到您制作的可比较对象中,以便缓存该值:
public class FileLmWrapper implements Comparable<FileLmWrapper> {
public final File f;
public final long lastModified;
public FileLmWrapper(File f) {
this.f = f;
lastModified = f.lastModified();
}
public int compareTo(FileLmWrapper other) {
return Long.compare(this.lastModified, other.lastModified);
}
}
答案 2 :(得分:1)
我不确定,但听起来它每次读取修改时间时都在进行磁盘I / O,因此速度很慢。简单地在对象中获取修改的时间和File对象,然后然后排序可能会更快。
答案 3 :(得分:1)
您的比较操作
@Override
public int compare(File f1, File f2) {
return (int)(f1.lastModified() - f2.lastModified());
}
不仅仅是一个getter,而是发出调用以从文件系统获取信息,因此排序的高响应时间也是由于lastModified()
的性能高于compare()
。
答案 4 :(得分:0)
在中实现的排序修改了快速排序调整的合并排序,其平均运行时间复杂度为O(nlogn)。
因此我们需要专注于你的文件操作,比如获取lastModifiedTime。您确定这些文件是本地文件还是共享驱动器,这会占用网络延迟?