Java 改造覆盖

Java 改造覆盖,java,caching,fileoutputstream,linkedhashmap,Java,Caching,Fileoutputstream,Linkedhashmap,如何覆盖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 removeEldes

如何覆盖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());

}
但我犯了一个错误

错误(15,27):中的removeEldestEntry(java.util.Map.Entry)无法覆盖java.util.LinkedHashMap中的removeEldestEntry(java.util.Map.Entry);重写的方法不会引发java.io.IOException

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

重写方法时,无法更改方法签名。因此,您需要在重写的方法中处理异常,而不是抛出异常


这篇文章很好地解释了如何使用try-and-catch:

您首先需要确保您的方法正确地覆盖了父级。您可以对签名进行一些小的更改,例如只抛出一个更具体的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
            }
        }
    }
}
private static final int MAX_ENTRIES_ALLOWED=100;
私有静态最终长最大文件大小=1L*1024*1024;//1 MB
受保护的布尔重构(Map.Entry最早){
if(size()最大文件大小){
//在此处执行一些操作以管理文件大小,例如重命名文件
//如果没有更详细的说明,您将无法轻松地从文件中删除对象
//高级文件结构,因为您正在编写任意大小的序列化文件
//对象。您需要对每个条目或包含进行某种标记
//每一条之前都有一个记录长度。然后你必须扫描并重建
//一个新文件。您不能轻松地删除文件中较早的字节,而不使用
//更高级的结构(如索引、固定大小的记录和
//可用空间列表,甚至数据库)。
}
FileOutputStream=null;
试一试{
fos=新文件输出流(objFile,true);//打开以进行追加
ObjectOutputStream oos=新的ObjectOutputStream(新的BufferedOutputStream(fos));
oos.writeObject(eldest.getValue());
oos.close();//关闭对象流以刷新剩余的生成数据(如果有)。
返回true;
}捕获(IOE异常){
//在此处记录错误或。。。。
抛出新的RuntimeException(e.getMessage(),e);//转换为RuntimeException
}最后{
如果(fos!=null){
试一试{
fos.close();
}捕获(IOE2异常){
//日志失败-无需抛出
}
}
}
}

+1完全正确。在签名方面,您的新方法必须是现有方法的“插入式”替换,这意味着从外部角度来看,它不必抛出任何(已检查的)异常。这通常会有点痛苦,我不认为有任何完全令人满意的方法可以克服这一点。顺便说一句,Removeedestentiry(最年长的)总是返回false。当您希望删除最旧的条目时,必须重写它以返回true。您的文件t.tmp将只保存最后删除的条目。这就是你想要的吗?这就是我需要的!谢谢!
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
            }
        }
    }
}