在一长串文件中查找最近修改的3个文件

时间:2013-01-17 05:40:15

标签: java file sorting memory memory-management

我有一个文件列表,我想对其进行排序并提取最后修改过的前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;
      }
    }
  });
}

问题

以上两种解决方案需要更多时间来执行&amp;记忆。我的文件列表包含大约300个tar文件,每个文件大小为200MB。所以它消耗更多的时间和存储器中。

有没有办法有效地处理这个问题?

每个比较操作都使用一个高内存的文件对象有没有办法释放内存并有效地处理它?<​​/ p>

4 个答案:

答案 0 :(得分:3)

你必须检查每个文件的lastModified,你不能改变它。你不需要做的就是排序所有元素只是为了获得前3名。如果你可以使用Guava,你可以使用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);

答案 1 :(得分: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());
    } 

}

答案 2 :(得分: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不保存/读取任何文件数据,只保存文件路径,没有性能/内存问题。这里唯一耗时的操作是从文件系统读取修改时间,这是无法避免的。

答案 3 :(得分: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实现将抛出异常,如果最后修改日期发生变化,因此比较会产生不同的值。