java - 将大型 HashMap 存储到 Java 文件中的方法?

标签 java hashmap

我有一个包含 20000 个条目的 HashMap 。 HashMap 的形式为,

Map<Integer,Map<String,Object>> mapOne

我有方法将 map 写入文件。

public void createFiles(String fileName, Map map) throws IOException {
        FileOutputStream fos = new FileOutputStream(fileName);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(map);
        oos.close();
}

此方法通过尝试将 mapOne 写入文件时出现 java 堆空间错误。有没有其他更好的方法将 map 存储到文件中供以后使用?

JDK版本:1.7.0_17 mapOne 中的 map 包含独特的元素,以及 map 中对象的频率。

得到的错误信息:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.io.ObjectOutputStream$HandleTable.growEntries(Unknown Source)
    at java.io.ObjectOutputStream$HandleTable.assign(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at java.util.HashMap.writeObject(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at java.util.HashMap.writeObject(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at TestIndex.AlignReads.createFiles(AlignReads.java:458)
    at TestIndex.AlignReads.loadInputFiles(AlignReads.java:241)
    at TestIndex.AlignReads.<init>(AlignReads.java:126)
    at TestIndex.AlignReads.main(AlignReads.java:493)

最佳答案

这似乎不是一个非常大的HashMap。在调用您的程序时,您应该考虑增加堆(“内存”)大小。对于 Oracle 的 JDK 版本 1.7.0_17,这可以通过命令行开关 -Xms1g -Xmx1g 来完成。此示例将最大堆设置为 1 GB。当然,要使其完全有效,机器必须具有足够的(虚拟)内存资源。默认值可以低至 64 MB(小于 1 GB 的 10%),具体取决于具体条件。

关于你的第二个问题,你需要具体说明你认为“更好”的是什么。也就是说,在大多数情况下,像您一样使用标准对象序列化 API 是最佳选择。

第二个最常见的替代方法(有些人可能会说它实际上是第一个)是将信息存储在数据库中并根据需要从该信息构造对象。显然,如果出于某种原因您同时需要内存中的所有信息,那么您的进步并不大。

第三种选择(如果由于某种原因对象序列化 API 在这种特殊情况下行为不当(我对此表示怀疑)是有效的),不是序列化整个 map ,而是一次序列化每个元素。甚至每个数据项。这需要您在标准 API 之上定义特定于应用程序的序列化协议(protocol)。不是特别困难,但可能值得单独提问。

关于java - 将大型 HashMap 存储到 Java 文件中的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18306392/

相关文章:

java - 如何在 RCP 工作台工具栏和 RCP View 之间进行通信

java - Hashtable 与 HashMap 中的哈希函数?

c++ - google/dense_hash_map的线程安全

java - 最小瓶 Java 代码中的意外结果

java - Guava:将 Multimap 转换为通用父类(super class)型是否有效?

java - 多次引用另一个类中的 HashMap 是否效率低下?

java - 如果两个不同的对象具有相同的哈希码会怎样?

java - HashMap 中的列表删除一个值

java - HttpClientErrorException.getStatusText 和 HttpClientErrorException.getResponseBodyAsString 之间的区别

java - 如何将 aws S3 集成到我的 android 应用程序中?