我正在生成具有32678个顶点的完整图形的随机边。所以,5亿+价值。
我使用HashMap将边作为键,使用随机边权重作为值。我一直遇到:
线程“main”中的异常java.lang.OutOfMemoryError:Java堆空间 在java.lang.StringBuilder.toString(StringBuilder.java:430)at pa1.Main.main(Main.java:19)上的pa1.Graph。(Graph.java:60)
此图表将用于构建最小生成树。
关于更好的数据结构或方法的任何想法?
我知道有更多的内存来分配更多的内存,但我更喜欢一个按原样运行的解决方案。
答案 0 :(得分:4)
HashMap
非常大,因为它将包含Doubles
(大写字母D),大大超过8个字节。 (更不用说Entry
)取决于实现和CPU芯片,但我认为每个至少16个字节,可能更多?
我认为您应该考虑将主要数据保留在一个巨大的double[]
中(或者,如果您可以节省一些准确性,float[]
)。这可以减少2倍或4倍的内存使用量。 (500M浮点数仅为“2GB”)然后使用整数索引到此数组中来实现边和顶点。例如,边可以是int [2]。这远离O-O,这里有一些严肃的挥手。 (我不明白你想要做的所有细微差别)
非常“老式”的风格,但需要更少的记忆。
更正 - 我认为边可能是int [4],顶点是int [2]。但是你明白了。实际上,对于边和顶点,您将拥有较少数量的对象,对于它们,您可以使用“真实”对象,地图等...
答案 1 :(得分:3)
由于它是一个完整的图形,因此毫无疑问边缘是什么。如何将这些边缘的标签存储在以某种方式排序的简单列表中?所以例如如果你有5个节点,边缘的权重将按如下方式排序:{1,2}, {1,3} {1,4} {1,5} {2,3} {2,4} {2,5} {3,4} {3,5} {4,5}
。
然而,正如@ BillyO'Neal指出的那样,这可能仍会占用8 GB的空间。您可能希望将此列表拆分为多个文件,同时维护这些文件的索引,建议一组权重在一个文件中结束的位置以及下一组权重开始的位置。
此外,鉴于您正在为图表找到MST,您可能还想查看以下文章:http://cvit.iiit.ac.in/papers/Vibhav09Fast.pdf。本文似乎基于Boruvka的算法(http://en.wikipedia.org/wiki/Bor%C5%AFvka's_algorithm; http://iss.ices.utexas.edu/?p=projects/galois/benchmarks/mst)。