2011-01-27 3 views
3

가장 오래된 항목을 파일로 저장하려면 removeEldestEntry 메서드를 재정의 할 수 있습니까? 또한 LinkedHashMap에서했던 것처럼 파일의 크기를 제한하는 방법도 있습니다.removeEldestEntry override

import java.util.*; 

public class level1 { 
private static final int max_cache = 50; 
private Map cache = new LinkedHashMap(max_cache, .75F, true) { 
protected boolean removeEldestEntry(Map.Entry eldest) { 
    return size() > max_cache; 
} 
}; 


public level1() { 
for (int i = 1; i < 52; i++) { 
    String string = String.valueOf(i); 
    cache.put(string, string); 
    System.out.println("\rCache size = " + cache.size() + 
         "\tRecent value = " + i + " \tLast value = " + 
         cache.get(string) + "\tValues in cache=" + 
         cache.values()); 

} 

내가 FileOutputStream에 사용하려고 : 여기에 코드입니다

private Map cache = new LinkedHashMap(max_cache, .75F, true) { 
    protected boolean removeEldestEntry(Map.Entry eldest) throws IOException { 
     boolean removed = super.removeEldestEntry(eldest); 
     if (removed) { 
      FileOutputStream fos = new FileOutputStream("t.tmp"); 
      ObjectOutputStream oos = new ObjectOutputStream(fos); 

      oos.writeObject(eldest.getValue()); 

      oos.close(); 
     } 
     return removed; 
    } 

을하지만 오류

오류 (15,27) 얻고있다 : 위해서, removeEldestEntry (java.util.Map에게 .Entry)는 java.util.LinkedHashMap에서 removeEldestEntry (java.util.Map.Entry)를 재정의 할 수 없습니다. 오버라이드 (override)되는 메소드는 java.io.IOException를 슬로우하지 않습니다.

IOExecptio 컴파일러는 IOexception 및 Filenotfoundexception을 처리 할 것을 요구하지 않습니다. 다른 방법이 있습니까? Pls는 예제 코드를 보여 주며, 나는 자바에서 새로 왔으며 단지 2 레벨 캐싱의 기본 원리를 이해하려고 노력했다. Thx

+0

BTW super.removeEldestEntry (장남)이 항상 false를 반환 여기

당신이 원하는 것을 할 수 있습니다 무언가이다. 가장 오래된 항목을 삭제하려는 경우 true를 반환하도록 재정의해야합니다. 파일 t.tmp는 마지막으로 삭제 된 항목 만 보유합니다. 이게 니가 의도 한거야? –

답변

3

당신은 당신의 방법을 제대로 부모를 우선 확인하는 첫번째 필요. 상위에 선언 된 확인 된 예외의 하위 클래스 인보다 구체적인 확인 예외 만 throw하는 등의 시그니처를 약간 변경하면됩니다. 이 경우 부모는 확인 된 예외를 선언하지 않으므로 더 이상 수정할 수 없으며 검사 된 예외를 throw하지 않을 수 있습니다. 따라서 로컬에서는 IOException을 처리해야합니다. 당신이 그것을 할 수있는 몇 가지 방법이 있습니다, 어떤 종류의 RuntimeException로 변환 및/또는 그것을 기록하십시오.

파일 크기가 염려되는 경우 마지막으로 제거 된 항목 만 유지하려는 것이 아니라 많은 항목을 보관하려는 경우가 많으므로 추가를 위해 파일을 열어야합니다.

실제로 장남을 제거하는 방법에서 true을 반환해야하며 요소를 제거해야하는지 결정해야합니다.

파일을 작업 할 때 try/finally를 사용하여 예외가 있어도 리소스를 닫아야합니다. 이것은 좀 못생긴 일을 할 수 있습니다 - 때로는 여분의 try/catch가 필요 없도록 close를 수행하는 유틸리티 메소드를 갖는 것이 좋습니다.

일반적으로 성능을 크게 향상시키는 파일 I/O에 대해 일부 버퍼링을 사용해야합니다. 이 경우 java.io.BufferedOutputStream에서 파일 스트림을 랩핑하고 ObjectOutputStream에 제공하십시오.

private static final int MAX_ENTRIES_ALLOWED = 100; 
private static final long MAX_FILE_SIZE = 1L * 1024 * 1024; // 1 MB 

protected boolean removeEldestEntry(Map.Entry eldest) { 
    if (size() <= MAX_ENTRIES_ALLOWED) { 
     return false; 
    } 

    File objFile = new File("t.tmp"); 
    if (objFile.length() > MAX_FILE_SIZE) { 
     // Do something here to manage the file size, such as renaming the file 
     // You won't be able to easily remove an object from the file without a more 
     // advanced file structure since you are writing arbitrary sized serialized 
     // objects. You would need to do some kind of tagging of each entry or include 
     // a record length before each one. Then you would have to scan and rebuild 
     // a new file. You cannot easily just delete bytes earlier in the file without 
     // even more advanced structures (like having an index, fixed size records and 
     // free space lists, or even a database). 
    } 

    FileOutputStream fos = null; 
    try { 
     fos = new FileOutputStream(objFile, true); // Open for append 
     ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(fos)); 

     oos.writeObject(eldest.getValue()); 
     oos.close(); // Close the object stream to flush remaining generated data (if any). 
     return true; 
    } catch (IOException e) { 
     // Log error here or.... 
     throw new RuntimeException(e.getMessage(), e); // Convert to RuntimeException 
    } finally { 
     if (fos != null) { 
      try { 
       fos.close(); 
      } catch (IOException e2) { 
       // Log failure - no need to throw though 
      } 
     } 
    } 
} 
+1

그게 내가 필요한거야! 고마워요! – BraginiNI

1

메서드를 재정의 할 때 메서드 서명을 변경할 수 없습니다. 따라서 오버라이드 된 메소드에서 던지지 않고 예외를 처리해야합니다.

이 시도하고 캐치 사용하는 방법에 대한 좋은 설명이 포함되어 있습니다 http://download.oracle.com/javase/tutorial/essential/exceptions/try.html

+0

+1 정확합니다. 새 메소드는 기존의 서명을 "드롭 인 (drop-in)"방식으로 대체해야합니다. 즉, 외부 관점에서 보면 예외를 throw하지 않아야합니다. 이것은 종종 약간의 고통이 될 수 있으며이를 극복하기위한 완전히 만족스러운 일반적인 접근법은 없다고 생각합니다. –