【发布时间】:2015-08-26 08:41:07
【问题描述】:
我有一个代价高昂的函数,将各种 double 变量作为输入:
public double f(double v1, double v2, double v3){
...
return output;
}
所以我尝试使用两种不同的策略来记忆它的输出。
嵌套哈希映射:
Map<Double,Map<Double,Map<Double,Double>>> map = new HashMap<>();
public double f(double v1, double v2, double v3){
// This is abbreviated: in my case I made sure to call only once each "get()"
if(map.containsKey(v1) && map.get(v1).containsKey(v2) && map.get(v1).get(v2).containsKey(v3))
return map.get(v1).get(v2).get(v3);
...
// calculations
...
// put "output" in the map (and create new intermediate HashMaps when needed)
...
return output;
}
自定义HashMap键:
public class DoubleKey {
public final double[] values;
public DoubleKey(double[] values){ this.values = values;}
@Override
public boolean equals(Object key){
if(key instanceof DoubleKey)
return Arrays.equals(values, ((DoubleKey)key).values);
return false;
}
@Override
public int hashcode(){
return Arrays.hashcode(values);
}
}
Map<DoubleKey,Double> map = new HashMap<>();
public double f(double v1, double v2, double v3){
DoubleKey key = new DoubleKey(new double[]{v1,v2,v3});
if(map.containsKey(key))
return map.get(key);
...
// calculations
...
map.put(key, output);
return output;
}
现在,我预计第二种方法会更快,因为它使用单个 Hashmap,并且总体感觉更优雅。但事实证明,与第一种方法相比,我从第二种方法中获得的好处更少,后者产生了很大的速度提升。
您知道为什么第二种方法效率较低吗?这是使用Arrays.equals() 和/或Arrays.hashcode() 的成本吗?
更一般地说,您知道其他更有效的记忆技术吗?
【问题讨论】:
-
java.lang.Object 只计算一次哈希码并存储它。我认为您也应该使用这种方法。此外,添加三个双字段而不是数组更有效。
-
您还可以使用比常规 Java 集合更有效的方法来存储来自 trove.starlight-systems.com 的 TObjectDoubleMap 等原始类型
-
请定义高效。
-
@OldCurmudgeon,我的意思是“快”
-
@sibnick,感谢您的提示!我尝试存储哈希码,但并没有做出太大的改变。
标签: java arrays hashmap memoization