Java Arrays.sort()需要很长时间

时间:2012-08-10 18:30:33

标签: java sorting

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

5 个答案:

答案 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。您确定这些文件是本地文件还是共享驱动器,这会占用网络延迟?