是否存在已经实现的数据结构,我可以使用它来分配给对象 (在我的例子中是一个边缘),一个整数?我正在从一个文件,10密耳顶点,60密耳边缘读取图形,并使用地图(cost.put(e,cost))为每个边缘分配成本。
我以这种方式创建成本地图:
costs = new HashMap<Edge,Integer>();
它给出的例外是:
java.lang.OutOfMemoryError: Java heap space
at java.util.HashMap.resize(Unknown Source)
at java.util.HashMap.addEntry(Unknown Source)
at java.util.HashMap.put(Unknown Source)
答案 0 :(得分:6)
HashMap
是基本Map
的正确数据结构。您遇到的问题是没有指示JVM保留足够的空间来将文件内容保存在内存中。使用-Xmx
标志启动JVM。例如,-Xmx1G
参数将允许它使用1千兆字节的内存。
答案 1 :(得分:6)
你有6e7边缘。普通对象占用24个字节(64位HotSpot),因此那里的1.44e9字节(1.5 GB)。现在,您将介绍可以想象的最有效的映射,仅添加6e7个引用和6e7 Integer
个对象。这是refs的另一个2.4e8字节和Integer
的1.44e9字节:另外1.5 GB,现在总共3 GB - 这是你问题的理论下限(模缓存,见下文)。
基于此,我建议您将Edge
课程扩展为另一个int
字段。这将大大减少您的内存占用。
但是,如果这不是一个选项,并且:
new Integer
,但Integer.valueOf
,自动装箱等,您将自动受益于内置的小整数缓存。如果整数假设范围更广,但仍有大量重复,则建议使用自定义缓存。
答案 2 :(得分:3)
除了更改jvms内存设置外,您还可以使用初始容量和负载平衡调整HashMap
内存管理。
Javadoc摘录:
HashMap的一个实例有两个影响其性能的参数: 初始容量和负载系数。容量是数量 哈希表中的桶,而初始容量就是 创建哈希表时的容量。负载系数是a 衡量哈希表在其之前可以获得多长的度量 容量自动增加。当中的条目数 哈希表超出了加载因子和当前的乘积 容量,哈希表重新哈希(即内部数据 重建结构),以便哈希表大约两次 桶的数量。
答案 3 :(得分:3)
而不是创建HashMap
costs = new HashMap<Edge,Integer>();
您可以将费用存储在Edge
对象中。
class Edge
{
Vertex a;
Vertex b;
int cost;
}
这样您就可以在系统中节省一些内存。
答案 4 :(得分:2)
回到原来的问题:你有边缘,有成本。由于图形稀疏,为什么不使用稀疏矩阵?也许对象到整数的映射并不是你真正需要和想要的。 你可以看看apache.commons.math,我认为他们有稀疏矩阵。此外,您需要考虑如何访问算法中的成本,选择适当的稀疏格式(基于列的游程编码/基于行的rle或其他)。或者你不关心,并使用任何,但是你应该在算法的开头转换这个东西。
答案 5 :(得分:1)
你确实意识到这需要一个全部的RAM,对吗?试试increasing the heap size,你会没事的......
回答你原来的问题:是的,这就是Map的用途......
答案 6 :(得分:1)
您必须为每个项目指定项目所需的堆空间
我认为您可以按照以下步骤操作:
Right mouse click - Run As - Run Configuration - Arguments - Vm Arguments, then add this -Xmx2048m
答案 7 :(得分:1)
也许你正在寻找的是TObjectIntHashMap这类似于HashMap<Edge, Integer>
,除了它将int
存储为原语可能会为你节省一些内存。当集合较大时(因为它更适合缓存),此集合也可以稍微快一些。
TObjectIntHashMap<Edge> costs = new TObjectIntHashMap<Edge>();
costs.put(e, cost); // cost is stored as a primitive not its wrapper object.