我需要存储一个包含邮政编码的二维矩阵,以及每个邮编之间的距离。我的客户端有一个计算距离的应用程序,然后存储在Excel文件中。目前,有952个地方。所以矩阵将有952x952 = 906304个条目。
我试图将其映射到HashMap [Integer,Float]。 Integer是两个字符串的哈希码,例如: “A”和“B”。浮点值是它们之间以km为单位的距离。
在填写数据时,我会在205k条目后运行OutOfMemoryExceptions。你有一个提示,我怎么能以聪明的方式存储它?我甚至不知道在整个记忆中是否都很聪明。我的选择是SQL和MS Access ......
问题是我需要非常快速地访问数据,这可能是我选择HashMap的原因,因为它在O(1)中运行以进行查找。
Thansk的回复和建议!
马
答案 0 :(得分:8)
2d数组会更有效。 您可以使用小型散列映射将952个位置映射到0到951之间的数字。 然后,就这样做:
float[][] distances= new float[952][952];
要查找,只需使用两个哈希查找将两个位置转换为两个整数,并将它们用作二维数组的索引。
通过这种方式,你可以避免浮动的装箱,以及大型hashmap的内存开销。
但是,906304真的不是那么多条目,你可能只需要增加Xmx最大堆大小
答案 1 :(得分:5)
我原本以为你可以动态计算距离。据推测有人已经这样做了,所以你只需要找出他们使用的算法和输入数据;例如每个邮政编码的名义中心的经度/纬度。
编辑:有两种常用的算法可以找到由经度/纬度对给出的两点之间的(近似)测地距离。
Vicenty formula基于椭圆近似。它更准确,但实施起来更复杂。
Haversine formula基于球面近似。它不太准确(0.3%),但实施起来更简单。
答案 2 :(得分:2)
您可以简单地增加JVM可用的内存吗?
java -Xmx512m ...
通过 default ,最大内存配置为64Mb。一些更多的调整技巧here。如果你能做到这一点,那么你可以保持数据在进行中并最大化性能(即你不需要动态计算)。
答案 3 :(得分:2)
我赞同Chi和Benjamin的答案,因为他们告诉你你需要做什么,但是当我在这里时,我想强调直接使用两个字符串的哈希码会让你陷入困境。您可能会遇到哈希冲突的问题。
如果你连接两个字符串(小心使用不能出现在地方指示符中的分隔符),并让HashMap发挥其魔力,这不会是一个问题,但方法你建议,使用两个字符串的哈希码作为密钥,这会让你陷入麻烦。
答案 4 :(得分:1)
您只需要更多内存。在启动Java进程时,请将其启动:
java -Xmx256M MyClass
-Xmx定义了最大堆大小,因此这表示进程最多可以为堆使用256 MB内存。如果你仍然用光,请继续将该数字提高,直至达到物理极限。
答案 5 :(得分:1)
最近我为我的硕士论文设定了类似的要求。
我最后使用的是使用double[]
而不是double[][]
的Matrix类,以减轻双重deref费用(data[i]
是一个数组,然后是array[i][j]
这是一个double
),同时允许VM分配一大块连续的内存:
public class Matrix {
private final double data[];
private final int rows;
private final int columns;
public Matrix(int rows, int columns, double[][] initializer) {
this.rows = rows;
this.columns = columns;
this.data = new double[rows * columns];
int k = 0;
for (int i = 0; i < initializer.length; i++) {
System.arraycopy(initializer[i], 0, data, k, initializer[i].length);
k += initializer[i].length;
}
}
public Matrix set(int i, int j, double value) {
data[j + i * columns] = value;
return this;
}
public double get(int i, int j) {
return data[j + i * columns];
}
}
这个类应该使用比HashMap
更少的内存,因为它使用原始数组(不需要装箱):它只需要906304 * 8 ~ 8 Mb
(对于 double < / strong> s)或906304 * 4 ~ 4 Mb
(对于浮动)。我的2美分。
NB 为简单起见,我省略了一些健全性检查
答案 6 :(得分:1)
以上有关堆大小的建议会有所帮助。但是,我不确定您是否准确描述了矩阵的大小。
假设您有4个位置。然后,您需要评估A-> B,A-> C,A-> D,B-> C,B-> D,C-> D之间的距离。这表明你的HashMap中有六个条目(4个选择2)。
这会让我相信你的HashMap的实际最佳大小是(952选择2)= 452,676; NOT 952x952 = 906,304。
当然,这只是假设您只存储单向关系(即从A-> B,但不是从B-> A,因为这是多余的),我建议你这样做,因为你是已经遇到内存空间问题。
编辑:应该说矩阵的大小不是最优的,而不是说描述不准确。
答案 7 :(得分:1)
当然,该解决方案会做出一些假设,在您的特定情况下可能会变得虚假,即您拥有邮政编码的经度和纬度数据,并且您关注的是如同苍蝇的距离和不像行车路线那样复杂。
如果这些假设是正确的,那么如果您需要处理更大的数据集,那么为一大堆内存交换一些计算可能会帮助您在将来扩展。
答案 8 :(得分:0)
创建一个新的类,其中包含2个位置名称的插槽。它始终将字母顺序的名字放在第一个插槽中。给它一个适当的equals和hashcode方法。给它一个compareTo(例如,按名称的字母顺序排序)。把它们全部扔进阵列中。解决。
此外,hash1 = hash2并不意味着object1 = object2。不要这样做。这是一个黑客。