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

我使用Java的Arrays.sort()函数按照上次修改时间对文件列表进行排序。 245个文件的排序大约需要5秒钟。 这对我来说似乎太长了。 我觉得它不应该超过0.5秒。 这是一个很好的假设吗? 我究竟做错了什么? 或者这听起来正常吗?

 public static class LastModifiedComparator implements Comparator { @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 :73 - Starting File Sort 2012-08-10 14:24:25,915 DEBUG http-8080-4 :75 - Done File Sort 

您需要改进Comparator逻辑。 您需要缓存 lastModified()值,因为该方法的实现非常慢。 我建议将File实例包装到您制作的类似对象中,以便缓存该值:

 public class FileLmWrapper implements Comparable { 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); } } 

File.lastModified必须转到操作系统来查询文件的最后修改时间 – 它没有被缓存。 你每次比较都要做两次,而Arrays.sort使用一个mergesort – O(n log n) 。 为n插入245,这是大约580次比较,或1100次调用操作系统以获得最后修改时间。 这意味着您每秒可以获得大约230个最后修改过的调用。 这看起来似乎有点慢,但肯定比JVM比较需要那么长时间

正如Marko Topolnik abd NgSan指出的那样,修复方法是首先缓存所有文件的最后修改时间。 我会通过创建一个结合了File和那个时间的新类对象,然后对这些对象进行排序来实现。 这样你只需要对File.lastModified 245次调用,并且排序大约需要1/5的时间。

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

你的比较操作

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

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

修改后的Quick Sort tuned Merge Sort中以java实现的排序,其平均运行时复杂度为O(nlogn)。
所以我们需要专注于你的文件操作,比如获取lastModifiedTime。 您确定这些文件是本地文件还是共享驱动器,这会占用网络延迟?