试图找到一种更有效的方法来过滤文件

时间:2012-03-27 00:34:00

标签: java

鉴于deviceIds列表,我试图提出一种更有效的处理重复项的方法。当在deviceId列表中找到重复项时,我只需要保留最新文件并删除其他文件。到目前为止,我提出的似乎工作正常,但我想知道它是否可以提高效率?我目前的方法似乎不能很好地扩展,例如,它在5秒内处理25,000个文件,但对于100,000个文件需要70秒。有什么想法吗?

List<File> filteredList;
        for(int i = 0; i < deviceIds.size(); i++) {
            if(i < (deviceIds.size()-1) && deviceIds.get(i).equals(deviceIds.get(i+1))) {
                filteredList = Lists.newArrayList(Iterables.filter(fileList, new DeviceIdFilter(deviceIds.get(i))));
                Collections.sort(filteredList, new OldestFileComparator());
                for(int t = 0; t < (filteredList.size()-1); t++) {
                    filteredList.get(t).delete();
                }
            }
        }

private static class DeviceIdFilter implements Predicate<File> {
    private String deviceId;
    private DeviceIdFilter(final String deviceId) {
        this.deviceId = deviceId;
    }
    @Override
    public boolean apply(final File file) {
        return file.getName().contains(deviceId);
    }
}

public class OldestFileComparator implements Comparator<File> {
    public int compare(File filea, File fileb) {
        if (filea.lastModified() > fileb.lastModified()) {
            return +1;
        } else if (filea.lastModified() < fileb.lastModified()) {
            return -1;
        } else {
            return 0;
        }
    }
}

编辑:

我实施了TacticalCoders解决方案,该解决方案运行得非常好,在0.60秒内处理100,000个文件。

    Map<String, List<File>> fileMap = new HashMap<String,List<File>>();
    String deviceId;
    List<File> deviceFileList;
    for(File file : fileList) {
        deviceId = getDeviceId(file.getName());
        if(fileMap.containsKey(deviceId)) {
            fileMap.get(deviceId).add(file);
        } else {
            deviceFileList = new LinkedList<File>();
            deviceFileList.add(file);
            fileMap.put(deviceId, deviceFileList);
        }
    }

    for (Map.Entry<String, List<File>> mapEntry : fileMap.entrySet()) {
        deviceFileList = mapEntry.getValue();
        if(deviceFileList.size() > 1) {
            Collections.sort(deviceFileList, new OldestFileComparator());
            for(int t = 0; t < (deviceFileList.size()-1); t++) {
                deviceFileList.get(t).delete();
            }
        }

1 个答案:

答案 0 :(得分:2)

  

我目前的方法似乎不能很好地扩展,例如,它   在5秒内处理25,000个文件,但在100,000秒内处理70秒   文件。有什么想法吗?

那是因为你有一个 O(n ^ 2)算法(如果碰巧大多数情况下它可能会退化到比 O(n ^ 2)更糟糕的程度重复,在这种情况下你除了你的两个for循环之外你还要做一个 O(n log n)排序,但我认为你没有10万个文件基本上是一样的复制)。

如果我正确地阅读了问题,您可以先进行第一次传递,在其中构建 Map&lt; String,List&lt; File&gt;&gt; (其中键将(sub)String对应到设备ID)。

在第一次传递之后,每个有重复的文件都会在一个包含至少两个条目的列表中,而每个没有重复的文件都在它自己的列表中。

然后,您将迭代地图,每当您找到包含多个条目的列表&lt;文件&gt; 时,您就会根据日期对该列表进行排序,并删除除最新文件之外的所有文件。

那会有用吗?

编辑您必须小心设备ID:我根本不知道它们的外观但是如果一个ID可以是“nop100”而另一个设备ID可以是比方说,“nop1000”,那么如果你在“nop1000”之前处理“nop100”,你可能会遇到包含方法调用的问题(因为“nop1000”会错误地匹配“nop100”的设备ID设备)。据我所知,这个问题存在于您发布的部分代码中。当然有一些解决方法,但如果不了解您正在处理的文件名类型,就很难走得更远。