15

我正在使用 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
4

5 回答 5

24

你需要改进你的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);
  }
}
于 2012-08-10T18:37:27.883 回答
23

File.lastModified必须去操作系统查询文件最后一次修改的时间——它没有被缓存。每次比较你都会这样做两次,并且Arrays.sort使用mergesort -- O(n log n)。插入 245n次,大约是 580 次比较,或 1100 次操作系统调用以获得最后修改时间。这意味着您每秒可以获得大约 230 个最后修改的调用。这看起来可能有点慢,但肯定比在 JVM 中进行这么长时间的比较更合理

正如上面 Marko Topolnik abd NgSan 指出的那样,解决方法是首先缓存所有文件的最后修改时间。我会通过创建一个结合文件和时间的新类对象来做到这一点,然后对这些对象进行排序。这样,您将只有 245 次调用File.lastModified,并且排序应该花费大约 1/5 的时间。

于 2012-08-10T18:36:49.430 回答
1

我不确定,但听起来每次您阅读修改时间时它都在进行磁盘 I/O - 因此速度很慢。简单地获取对象中的修改时间以及 File 对象,然后排序可能会更快。

于 2012-08-10T18:37:15.773 回答
1

您的比较操作

@Override
public int compare(File f1, File f2) {
    return (int)(f1.lastModified() - f2.lastModified());
}  

不仅仅是一个 getter,而是发出一个从文件系统获取信息的调用,因此排序的高响应时间也是由于lastModified()than的性能compare()

于 2012-08-10T18:38:52.810 回答
0

在修改后的快速排序中在 java 中实现的排序调整了合并排序,其平均运行时间复杂度为 O(nlogn)。
所以我们需要专注于你的文件操作,比如获取 lastModifiedTime。您确定这些文件是需要网络延迟的本地文件或共享驱动器吗?

于 2012-08-10T18:35:28.473 回答