有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java重构重写

如何覆盖RemoveEdestEntry方法以将最旧的条目保存到文件中?还有如何像我在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;
    }

但我犯了一个错误

Error(15,27): removeEldestEntry(java.util.Map.Entry) in cannot override removeEldestEntry(java.util.Map.Entry) in java.util.LinkedHashMap; overridden method does not throw java.io.IOException

如果没有IOExecutio,编译器会要求处理IOexception和Filenotfoundexception。 也许还有另一种方式存在?请给我看示例代码,我是java新手,只是想了解2级缓存的基本原理。Thx


共 (2) 个答案

  1. # 1 楼答案

    您首先需要确保您的方法正确覆盖父级。您可以对签名进行一些小的更改,例如只抛出一个更具体的checked异常,该异常是父级中声明的checked异常的子类。在这种情况下,父级不会声明任何选中的异常,因此您不能进一步细化该异常,也不能抛出任何选中的异常。因此,您必须在本地处理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
                }
            }
        }
    }