Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中各种输入函数的记忆_Java_Arrays_Hashmap_Memoization - Fatal编程技术网

Java中各种输入函数的记忆

Java中各种输入函数的记忆,java,arrays,hashmap,memoization,Java,Arrays,Hashmap,Memoization,我有一个代价高昂的函数,它将各种双变量作为输入: public double f(double v1, double v2, double v3){ ... return output; } 所以我试着用两种不同的策略记下它的输出 嵌套哈希映射: Map Map=newhashmap(); 公共双f(双v1、双v2、双v3){ //这是缩写:在我的例子中,我确保每个“get()”只调用一次 if(map.containsKey(v1)和&map.get(v1.containsK

我有一个代价高昂的函数,它将各种
变量作为输入:

public double f(double v1, double v2, double v3){
    ...
    return output;
}
所以我试着用两种不同的策略记下它的输出

嵌套哈希映射:
Map Map=newhashmap();
公共双f(双v1、双v2、双v3){
//这是缩写:在我的例子中,我确保每个“get()”只调用一次
if(map.containsKey(v1)和&map.get(v1.containsKey(v2)和&map.get(v1.get(v2.containsKey(v3))
返回map.get(v1.get(v2.get)(v3);
...
//计算
...
//将“输出”放在映射中(并在需要时创建新的中间哈希映射)
...
返回输出;
}
自定义哈希映射键:
公共类双密钥{
公共价值观;
公钥(双[]值){this.values=values;}
@凌驾
公共布尔等于(对象键){
if(双钥匙的钥匙实例)
返回数组.equals(值,((双键)键).values);
返回false;
}
@凌驾
公共int hashcode(){
返回数组。哈希代码(值);
}
}
Map Map=newhashmap();
公共双f(双v1、双v2、双v3){
DoubleKey=新的DoubleKey(新的double[]{v1,v2,v3});
if(地图容器(图例))
返回map.get(key);
...
//计算
...
map.put(键,输出);
返回输出;
}

现在,我希望第二种方法更快,因为它使用一个Hashmap,总体上感觉更优雅。但事实证明,与第一种方法相比,我从第二种方法中获得的好处较少,因为第一种方法可以大大提高速度

你知道为什么第二种方法效率较低吗?是使用
Arrays.equals()
和/或
Arrays.hashcode()
的成本吗


一般来说,你知道其他更有效的记忆技术吗?

这两种解决方案并不相同。第一个硬编码只支持3个双参数,而第二个硬编码只支持任意数量的参数

如果只需要支持3个参数,我认为保存3个实例变量更有效:

编辑:以下注释将使用varargs-ctor的原始答案替换为显式的单个args。可能效率更高(不构成aray)。还将实例变量设置为final,以启用编译器优化

public class DoubleKey
{
    final double arg1, arg2, arg3;
    final int hashCode;

    public DoubleKey(double arg1, double arg2, double arg3)
    {
        this.arg1 = arg1;
        this.arg2 = arg2;
        this.arg3 = arg3;
        hashCode = Objects.hash(arg1, arg2, arg3);
    }

    @Override
    public boolean equals(Object key)
    {
        if (key instanceof DoubleKey) {
            DoubleKey dk = (DoubleKey) key;
            return arg1 == dk.arg1 && arg2 == dk.arg2 && arg3 == dk.arg3;
        }
        return false;
    }

    @Override
    public int hashCode()
    {
        return hashCode;
    }
}
构造DoubleKey实例现在是一个很好的例子


DoubleKey key=newdoublekey(v1、v2、v3)

java.lang.Object只计算一次哈希代码并存储它。我认为你也应该使用这种方法。此外,添加三个双字段(而不是数组)更有效。此外,您还可以使用比常规java集合更有效的方法来存储基本类型,如来自Please define efficient的TObjectDoubleMap。@OldCurmudgeon,我的意思是“快”@sibnick,谢谢您的提示!我试着存储hashcode,但是没有什么大的改变。为什么不
public DoubleKey(double value1,double value2,double value3){…}
?你如何计算一个hashcode?我不知道commons HashCodeBuilder的效率有多高,也不知道如何用3个双值构造hash代码。我很高兴见到你<代码>长tmp=Double.doubleToLongBits(v1)^ Double.doubleToLongBits(v2)^ Double.doubleToLongBits(v3);int散列=(int)((tmp>>>32)^tmp)commons HashCodeBuilder的效率它成为问题的可能性很小。我要说的是,担心常用API的效率是一种浪费,您可能正在开发特性。但若这样的话,我会用其中一个而不是自己滚动<代码>@Cached public which boo()已排序。
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;
}
public class DoubleKey
{
    final double arg1, arg2, arg3;
    final int hashCode;

    public DoubleKey(double arg1, double arg2, double arg3)
    {
        this.arg1 = arg1;
        this.arg2 = arg2;
        this.arg3 = arg3;
        hashCode = Objects.hash(arg1, arg2, arg3);
    }

    @Override
    public boolean equals(Object key)
    {
        if (key instanceof DoubleKey) {
            DoubleKey dk = (DoubleKey) key;
            return arg1 == dk.arg1 && arg2 == dk.arg2 && arg3 == dk.arg3;
        }
        return false;
    }

    @Override
    public int hashCode()
    {
        return hashCode;
    }
}