我有一个包含20000个条目的散列图。 hashmap的格式为
Map<Integer,Map<String,Object>> mapOne
我有将地图写入文件的方法。
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堆空间错误。有没有其他更好的方法将地图存储到文件中供以后使用?
JDK版本:1.7.0_17 mapOne中的地图包含唯一的元素,其中包含地图中对象的频率。
获得的错误消息:
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)
答案 0 :(得分:0)
这似乎不是一个非常大的HashMap。在调用程序时,应考虑增加堆(“内存”)大小。对于Oracle的JDK版本1.7.0_17,可以使用命令行开关-Xms1g -Xmx1g
完成此操作。此示例将最大堆设置为1 GB。为了使其变得完全有效,机器必须具有足够的(虚拟)内存资源。默认值可以低至64 MB(低于1 GB的10%),具体取决于具体条件。
关于你的第二个问题,你需要指出你认为“更好”的东西。也就是说,在大多数情况下,使用标准对象序列化API是最佳选择。
第二种最常见的替代方案(有些人可能会说它确实是第一种)是将信息存储在数据库中并根据需要从该信息构造对象。显然,如果出于某种原因你需要同时在内存中获取所有信息,那么你的进步就不多了。
第三种替代方法(在某些情况下,由于某些原因,在这种特殊情况下,对象序列化API行为不当(我怀疑))是有效的,不是一次序列化整个地图,而是每个元素。甚至每个数据项。这要求您在标准API之上定义特定于应用程序的序列化协议。不是很困难,但可能需要另外一个问题。
答案 1 :(得分:0)
也许,您正在序列化引用您不希望序列化的大对象的对象。取自java.awt.Component javadoc:
的示例开发人员将一如既往地考虑其影响 使对象可序列化。需要注意的一个问题是:
import java.awt.*;
import java.awt.event.*;
import java.io.Serializable;
class MyApp implements ActionListener, Serializable
{
BigObjectThatShouldNotBeSerializedWithAButton bigOne;
Button aButton = new Button();
MyApp()
{
// Oops, now aButton has a listener with a reference
// to bigOne!
aButton.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
System.out.println("Hello There");
}
}
在此示例中,单独序列化aButton将导致MyApp及其引用的所有内容也被序列化。该 问题是听众是巧合的序列化,而不是 设计。