序列化后在几个类中使用相同的Map?

时间:2016-09-21 11:37:55

标签: java serialization hashmap

我的应用程序在停止之前保存一个hashmap,当它再次启动时加载相同的hashmap,以便对其进行更改。我正在使用序列化。

存储类:

public class Storage {

private Map<String, String> storage;
private String projectStorageFilePath;

public Storage() {
    this.storage = new ConcurrentHashMap<String, String>();
    makeDir();
}

/**
 * If the file in which the map objects will be saved doesn't exist in the
 * user home directory it creates it.
 */
private void makeDir() {
    File projectHomeDir = new File(System.getProperty("user.home"), ".TestMap");
    String projectHomeDirPath = projectHomeDir.getAbsolutePath();
    File projectStorageFile = new File(projectHomeDirPath, "storage.save");
    projectStorageFilePath = projectStorageFile.getAbsolutePath();
    if (!projectHomeDir.exists()) {
        projectHomeDir.mkdir();
        try {
            projectStorageFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

@SuppressWarnings("unchecked")
public boolean load() {
    boolean isLoaded = false;
    ObjectInputStream ois = null;
    try {

        File file = new File(projectStorageFilePath);
        if (file.length() != 0) {

            //loading the map 
            ois = new ObjectInputStream(new FileInputStream(file));
            storage = (ConcurrentHashMap<String, String>) ois.readObject();

            isLoaded = true;

        }
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != ois) {
                ois.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return isLoaded;
}

public boolean save() {
    boolean isSaved = false;
    ObjectOutputStream oos = null;
    try {

        //saving
        oos = new ObjectOutputStream(new FileOutputStream(projectStorageFilePath));
        oos.writeObject(storage);

        isSaved = true;

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != oos) {
                oos.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return isSaved;
}

public Map<String, String> getStorage() {
    return this.storage;
}
}

我正在尝试使用该hashmap执行某些操作的类:

public class DoSomethingWithMap {

private Map<String, String> storage;

public DoSomethingWithMap(Map<String, String> storage) {
    this.storage = storage;
}

public void addToMap(String key, String value) {
    this.storage.put(key, value);
}
public void printMap() {
    System.out.println(this.storage);
}
}

当我第一次运行时它运行良好:

public class Main {

public static void main(String[] args) {
    Storage s = new Storage();
    DoSomethingWithMap something = new DoSomethingWithMap(s.getStorage());

    if (s.load()) {
        System.out.println(s.getStorage());
    }

    something.addToMap("2", "test2");
    something.addToMap("4", "test4");
    something.addToMap("5", "test5");

    if (s.save()) {
        System.out.println(s.getStorage());
    }
 }
}

输出:

{}           //empty map which is ok because it has never been saved before
{3=test3, 4=test4, 5=test5} //changes during runtime are saved

问题是当我再次启动Main并尝试更改已保存的地图时:

public static void main(String[] args) {
    Storage s = new Storage();
    DoSomethingWithMap something = new DoSomethingWithMap(s.getStorage());

    if (s.load()) {
        System.out.println(s.getStorage());
    }

    something.printMap();

    something.addToMap("6", "newTest");
    something.addToMap("7", "newTest");
    something.addToMap("8", "newTest");

    something.printMap();

    if (s.save()) {
        System.out.println(s.getStorage());
    }
}

输出:

{3=test3, 4=test4, 5=test5}         //loading the map works fine
{}                                 //here it should be same as previous line but is not
{6=newTest, 7=newTest, 8=newTest} //DoSomethingWithMap.printMap is printing only the changes during runtime
{3=test3, 4=test4, 5=test5}      // changes during runtime are not saved

很明显DoSomethingWithMap类没有使用给它的地图。为什么?哪个地图正在使用?我该如何解决这个问题?

谢谢。

1 个答案:

答案 0 :(得分:0)

您正在加载方法中创建Map的新实例:

storage = (ConcurrentHashMap<String, String>) ois.readObject();

要解决此问题,您可以清除当前地图,然后添加已加载的地图中的所有值:

//loading the map
ois = new ObjectInputStream(new FileInputStream(file));
storage.clear();
storage.putAll((ConcurrentHashMap<String, String>) ois.readObject());

为防止将来出现此类错误,您可以将这些字段设为最终字段,这样您就会收到错误报告。