Java 试图找到一种更有效的过滤文件的方法
给出一个DeviceID列表,我正试图想出一种更有效的方法来处理重复项。当在deviceId列表中发现重复文件时,我只需要保留最新的文件并删除其他文件。到目前为止,我提出的方案似乎还可以,但我想知道是否可以提高效率?我目前的方法似乎不能很好地扩展,例如,它在5秒内处理25000个文件,但处理100000个文件需要70秒。有什么想法吗Java 试图找到一种更有效的过滤文件的方法,java,Java,给出一个DeviceID列表,我正试图想出一种更有效的方法来处理重复项。当在deviceId列表中发现重复文件时,我只需要保留最新的文件并删除其他文件。到目前为止,我提出的方案似乎还可以,但我想知道是否可以提高效率?我目前的方法似乎不能很好地扩展,例如,它在5秒内处理25000个文件,但处理100000个文件需要70秒。有什么想法吗 List<File> filteredList; for(int i = 0; i < deviceIds.size(); i++
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;
}
}
}
列表过滤器列表;
对于(int i=0;ifileb.lastModified()){
返回+1;
}else if(filea.lastModified()
编辑:
我实现了TacticalCoders解决方案,它工作得非常出色,在0.60秒内处理了100000个文件
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();
}
}
Map fileMap=newhashmap();
字符串设备ID;
列表设备文件列表;
用于(文件:文件列表){
deviceId=getDeviceId(file.getName());
if(fileMap.containsKey(deviceId)){
获取(设备ID).add(文件);
}否则{
deviceFileList=新链接列表();
添加(文件);
put(deviceId,deviceFileList);
}
}
对于(Map.Entry mapEntry:fileMap.entrySet()){
deviceFileList=mapEntry.getValue();
如果(deviceFileList.size()>1){
排序(deviceFileList,new-OldestFileComparator());
对于(int t=0;t<(deviceFileList.size()-1);t++){
deviceFileList.get(t.delete();
}
}
例如,我目前的方法似乎不能很好地扩展
5秒内处理25000个文件,但100000个文件需要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;
}
}
}
这是因为你有一个O(n^2)算法(如果你碰巧有很多重复的,它可能会退化到比O(n^2)更糟糕的程度,在这种情况下,除了你的两个for循环外,你还要做一个O(n log n)排序,但我认为你没有100000个文件基本上总是相同的重复)
如果我正确地理解了这个问题,您可以只做第一步,在这里您将构建一个映射(在这里,键将是对应于设备ID的(子)字符串)
在第一次传递之后,每个具有重复项的文件都将位于至少包含两个条目的列表中,而每个没有重复项的文件都将位于其自己的列表中
然后在地图上迭代,每次找到包含多个条目的列表时,根据日期对列表进行排序,并删除除最新文件以外的所有文件
这样行吗
编辑你必须小心使用你的设备ID:我根本不知道它们是什么样子,但是如果一个ID可以是,比如说“nop100”,而另一个设备ID可以是,比如说“nop1000”,那么如果你在“nop1000”之前处理“nop100”,你的contains方法调用可能会遇到麻烦(因为“nop1000”会错误地匹配“nop100”设备)。据我所知,这个问题也存在于您发布的部分代码中。当然有解决方法,但如果不了解您正在处理的文件名类型,则很难进一步解决。您可以查看一种将列表划分为较小列表(如25000)的方法执行排序方法,然后使用mergesort类算法将它们合并在一起。一个更简单的比较器将返回
filea.lastModified().compareTo(fileb.lastModified())
。不是更快,只是更干净一点。但要注意空值(也是实现中的一个问题).TacticalCoder,感谢您提供了出色的解决方案。我实现了这一点,处理同一组100000个文件只需0.60秒。至于DeviceID,它们始终是固定长度(16个字符),因此所包含的字符串似乎是合适的。@Hoofamon:great:)哦,好的,如果设备ID总是16个字符长,那么您应该不会有任何问题。