2012-03-27 5 views
3

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 초에서 10 만 개 파일을 구현했습니다.

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

당신의 목록을 더 작은 것들 (25,000 등)로 나누는 방법을 당신의 sort 메쏘드가 할 수 있고, 그 다음 메르코수르 종류의 알고리즘과 병합합니다. –

+0

더 간단한 비교기는'filea.lastModified(). compareTo fileb.lastModified())'. 빠르지 않고, 조금만 청소하십시오. 그러나 null을주의하십시오 (구현시에도 문제가 있음). –

답변

2

내 현재의 방법은 예를 들어, 잘 확장하지 않는 것, 그것은 5 초에 25,000 파일을 처리하지만, 100,000 파일을 70 초 정도 걸립니다. 이견있는 사람? 당신이 (당신이 대부분 중복이 일어날 경우 잠재적 O (N^2)보다 훨씬 악화로 전락 할 수있는 O (N^2) 알고리즘을 가지고 있기 때문에,이다

경우에 당신 ' do (n log n) 두 개의 루프에 추가적으로 정렬을 수행하고 있지만 기본적으로 항상 동일한 복제본 인 100,000 개의 파일이 없습니다.

난 당신이 >>을 지도 < 문자열, 목록 < 파일을 구축 할 위치를 올바르게 단지 첫 번째 패스를 할 수있는 문제를 읽을 경우 (여기서 중요한 것 장치 ID에 해당하는 (하위) 문자열) . 그 첫 번째 패스 중복이없는 모든 파일이 자신의 목록에있을 것입니다 동안 두 개 이상의 항목이 목록에있을 것입니다 중복이있는 모든 파일을 한 후

.

당신은 다음지도를 반복 것하고 매번 두 개 이상의 항목이있는 목록 < 파일>을 찾아, 당신은 날짜에 따라 그 목록을 정렬하고 최신 파일을 제외하고 모두 삭제합니다.

그게 가능할까요?

EDIT 사용자는 기기 ID에주의해야합니다. 어떤 모양인지는 모르지만 한 ID가 'nop100'이고 다른 기기 ID가 ' nop1000 "을 처리하는 경우"nop1000 "앞에"nop100 "을 처리하면 메서드 호출이 포함 된 문제가 발생할 수 있습니다 ("nop1000 "이"nop100 "장치의 장치 ID와 잘못 일치하기 때문에). 내가 아는 한이 문제는 부분 코드에도 있습니다. 물론 해결 방법이 있지만 처리중인 파일 이름의 종류에 대해 알지 못하면 더 이상 진행하기가 어렵습니다.

+0

+1; 이것이 갈 길입니다. –

+0

TacticalCoder, 훌륭한 솔루션에 감사드립니다. 이것을 구현하고 같은 세트의 100,000 개의 파일을 처리하는 데 단지 0.60 초 밖에 걸리지 않았습니다.deviceIds는 항상 고정 길이 (16 자)이므로 포함 된 문자열이 적절하게 보입니다. – Hoofamon

+0

@Hoofamon : 위대한 :) 오케이, 장치 ID가 항상 16 자라면 문제가 없어야합니다. – TacticalCoder

관련 문제