鉴于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();
}
}
答案 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设备)。据我所知,这个问题存在于您发布的部分代码中。当然有一些解决方法,但如果不了解您正在处理的文件名类型,就很难走得更远。