自定义HashMap-Key (Java)极大地降低了性能



这是我的第一个问题,但我希望我能提供所有需要的信息。
如果不是,请让我知道!


我的问题:我尝试通过添加HashMap来存储已经处理过的结果来改进我的回溯算法。为此,我为该HashMap的键创建了一个自己的类。在这里,我覆盖了。equals()-和。hashcode()-方法。
但是如果我试图把这个键和它的值放入映射中,它会花费很多时间,所以算法变得比没有映射的回溯算法更低效。
为了解决这个问题,我将HashMap-Key更改为String,并在key类中添加了一个. tostring()方法。这工作得很好,而且相当快。(奇怪的是:.toString().hashCode()产生很多负值,但似乎工作)

现在我的问题:
如果您创建自己的密钥,它是否总是慢那么多?
我试图自己找到这个问题的答案,我发现的唯一方法是改变。hashcode()或使用HashMap-Constructor的参数。
我尝试了这两种方法,并为我的测试环境导出了生成的HashCodes,我没有发现任何重复,尽管我知道,这不是一个"好"的哈希码方法!

这是我的HashKey-Class的副本(变量和方法的名称已更改):

public class HashKey {
    private final int int0, int1, int2;
    public HashKey(int int0, int int1, int int2) {
        this.int0 = int0;
        this.int1 = int1;
        this.int2 = int2;
    }
    public int getInt0() {
        return this.int0;
    }
    public int getInt1() {
        return this.int1;
    }
    public int getInt2() {
        return this.int2;
    }
    @Override
    public int hashCode() {
        final int prime1 = 107;
        final int prime2 = 227;
        final int prime3 = 499;
        int result = 1;
        result = prime1 * result + this.int2;
        result = prime2 * result + this.int1;
        result = prime3 * result + this.int0;
        return result;
     }
    @Override
    public String toString() {
        return "Int0: " + this.int0 + " Int1: " + int1 + " Int2: " + int2;
    }
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof HashKey) {
            boolean eq0, eq1, eq2;
            eq0 = this.int0 == ((HashKey) obj).getInt0();
            eq1 = this.int1 == ((HashKey) obj).getInt1();
            eq2 = this.int2 == ((HashKey) obj).getInt2();
            if (eq0 && eq1 && eq2) {
                return true;
            }
        }
        return false;
    }
}  

在我的main-Class中,我使用这个:

HashMap<HashKey, List<Object>> storedResults = new HashMap<HashKey, List<Object>>();  
int x1,x2,x3;  
Object obj;  
// later in a method:
storedResults.put(new HashKey(x1,x2,x3), obj);

如果我将键的类型更改为字符串并将该字符串放入Map中,它可以正常工作!所以HashKey.hashCode()方法和算法的其余部分工作得很好,而且相当快。

有没有人知道,我可以做什么来使用这个HashKey?对于这个算法来说,它不是那么重要,但我想知道它对未来的算法!

如果有任何问题或批评:他们非常欢迎!

提前感谢!

Klumbe

试试这个:简化您的equals(..) -方法,并且不要多次计算hashCode

public final class HashKey {
    private final int int0, int1, int2;
    private final int hashCode;
    public HashKey(int int0, int int1, int int2) {
        this.int0 = int0;
        this.int1 = int1;
        this.int2 = int2;
        hashCode=107*int0+227*int1+499*int2;
    }
    @Override
    public final int hashCode() {
        return hashCode;
    }
    @Override
    public final boolean equals( finalObject obj) {
        if (!obj instanceof HashKey)
            retun false;
        HashKey other = (HashKey)obj;
        return int0 == other.int0 && int1 == other.int1 &&  int2 == other.int2;
    }
}  

参考fge的注释,我修改了代码

你的类几乎是不可变的:你所有的实例成员都是final,只有类本身也需要是final。

但是由于您的所有实例成员都是final,您也可以在构建时计算哈希码:

// Add as member:
private final int hashCode;
public HashKey(int int0, int int1, int int2) {
    this.int0 = int0;
    this.int1 = int1;
    this.int2 = int2;
    hashCode = // calculate hash code here
}
public int hashCode()
{
    return hashCode;
}

顺便说一下,负哈希码没什么好担心的。毕竟,.hashCode()返回一个int。

最新更新