3

removeEldestEntry メソッドを上書きして最古のエントリをファイルに保存するにはどうすればよいですか? また、LinkedHashMap で行ったようにファイルのサイズを制限する方法。コードは次のとおりです。

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) をオーバーライドできません。オーバーライドされたメソッドは java.io.IOException をスローしません

IOExecptio がないと、コンパイラは IOexception と Filenotfoundexception の処理を​​要求します。多分別の方法が存在しますか?サンプルコードを教えてください。私はJavaが初めてで、2レベルキャッシングの基本原則を理解しようとしています。どうも

4

2 に答える 2

3

まず、メソッドが親を適切にオーバーライドしていることを確認する必要があります。親で宣言されたチェック済み例外のサブクラスである、より具体的なチェック済み例外のみをスローするなど、署名にいくつかの小さな変更を加えることができます。この場合、親はチェック済み例外を宣言していないため、それをさらに改良することはできず、チェック済み例外をスローすることはできません。IOExceptionそのため、ローカルで処理する必要があります。それを行うにはいくつかの方法がありRuntimeException、何らかの種類に変換したり、ログに記録したりします。

ファイル サイズが気になる場合は、最後に削除されたエントリだけを保持するのではなく、多くのエントリを保持する必要があるため、ファイルを開いて追加する必要があります。

メソッドから戻っtrueて最年長の要素を実際に削除する必要があり、要素を削除する必要があるかどうかを判断する必要があります。

ファイルを操作するときは、try/finally を使用して、例外が発生した場合でもリソースを確実に閉じる必要があります。これは少し見苦しくなります - 余分な try/catch を必要としないように、終了を行うためのユーティリティ メソッドがあると便利な場合があります。

一般に、パフォーマンスを大幅に向上させるファイル 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
            }
        }
    }
}
于 2011-01-27T20:40:10.940 に答える
2

メソッドをオーバーライドするときにメソッド シグネチャを変更することはできません。したがって、例外をスローするのではなく、オーバーライドされたメソッドで例外を処理する必要があります。

これには、try と catch の使用方法に関する適切な説明が含まれています: http://download.oracle.com/javase/tutorial/essential/exceptions/try.html

于 2011-01-27T15:21:18.473 に答える