2013-01-17 34 views
4

我有一个文件列表,我想排序并提取前3个最后修改。找到文件的长列表中的3个最近修改的文件

约束:我不能对下游应用

我目前的选择

解决方案使用Java 7由于兼容性问题1

File[] files = directory.listFiles();  
Arrays.sort(files, new Comparator<File>(){ 
    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个每个大小为200MB的tar文件。所以它消耗更多的时间内存。

有什么办法可以有效地处理这个问题吗?

每个比较操作使用的是高内存的文件对象是否有任何方式来释放内存并对其进行有效处理?

+0

我认为你的记忆和时间问题并不是由于你对300个物品的排序(无论如何都在记忆中)。也许你不止一次地进行这种表演? – Howard

+0

不,我正在使用上述两种解决方案中的任何一种。 “反正在记忆中”你的意思是什么?我如何清除一旦操作完成。 – Wills

+3

“文件”对象不是一个昂贵的对象!它只包含文件名,而不包含文件的内容。所以文件大小完全不相关。 –

回答

3

你可以做得更快。

Arrays.sort(...)使用“快速排序”,这需要执行〜n * ln(n)操作。

本示例仅通过整个数组执行一次迭代,即〜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()); 
    } 

} 
+0

请删除“近6倍”的说法。通过在复杂性公式中插入数字,您可能无法比较不同算法的运行时间。结论是正确的 - 但是论点是有缺陷的。 – Howard

+0

我同意,这并不完全正确;这只是为了让人们“感受到不同”。 –

+0

谢谢@AlexKreutznaer。您的解决方案不适用于所有情况下的情况,例如考虑以下内容并针对您的算法进行追踪。文件名:FXXXXXXXXX改良07:00 HRS 文件名:FXXXXXXXXX改良07:40 HRS 文件名:MXXXXXXXXX改良05:00 HRS 文件名:YXXXXXXXXX改良10:00 <\code> 文件名:YXXXXXXXXX修改04:00 HRS – Wills

3

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

Ordering<File> ordering = Ordering.from(new Comparator(){ 
     public int compare(File f1, File f2) 
     { 
      return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); 
     }); 

List<File> max3 = ordering.greatestOf(Arrays.asList(directory.listFiles()), 3); 
0

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

Arrays.sort(files, new Comparator<File>() { 
     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不保存/读取任何文件数据,但只有文件路径,它没有性能/内存问题。这里唯一耗时的操作是从文件系统读取无法避免的修改时间。

+0

Long.compare出现在Java 7中,并且问题提出了非Java 7解决方案。 –

+0

现在,您已将代码更改为无法编译的代码(不兼容类型,int/long)。 –

+0

与原始代码相比,这是为什么改进? –

0

你的问题是,获取最后的修改日期是一个相对昂贵的操作,因为它涉及到操作系统的逻辑。因此,如果您不介意获取最新的最新值,则可以将文件包装到可比较的类中。

public class LastModifiedFile implements Comparable<LastModifiedFile> { 

    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的实现会抛出一个异常,如果最后一次修改日期发生变化,因此比较会导致不同的值。

相关问题