2009-07-30 107 views
11

我记得eclipse和想法有这个模板来根据它的属性自动创建一个对象的hashCode。从字符串和int创建哈希

如果使用数字和字符串的策略之一是这样的。

return stringValue.hashCode() + intValue * 32; 

这种东西就是这样。

我没有,也没有日食或想法在手边,我想创建这样的功能。

EDIT

基于I创建这个微型类

class StringInt { 
     private final String s; 
     private final int i; 

     static StringInt valueOf(String string , int value) { 
      return new StringInt(string, value); 
     } 
     private StringInt(String string, int value) { 
      this.s = string; 
      this.i = value; 
     } 
     public boolean equals(Object o) { 
      if(o != null && o instanceof StringInt){ 
       StringInt other = (StringInt) o; 
       return this.s == other.s && this.i == other.i; 
      } 

      return false; 
     } 
     public int hashCode() { 
      return s != null ? s.hashCode() * 37 + i : i; 
     } 
    } 

这个类的答案是要用作键大的存储器映射(> 10K元素)我不希望每次迭代它们以查找String和int是否相同。

谢谢。

ps .. mmh可能它应该是名称StringIntKey。

+0

奥斯卡,我认为这是一个很好的课堂。 hashCode方法清晰,可靠且高效。 怎么样防止字符串为空?在你的构造函数中,如果它是null,则抛出一个NPE。然后你可以在equals和hashCode中删除那些空警号。 最后,为这样的问题保留一份“Effective Java”的副本。 Eclipse和IDEA创建的hashCode方法基于该书。 – 2009-07-31 07:23:56

+0

在你的equals方法中,应该比较字符串use equals而不是==。 – 2009-07-31 15:09:12

回答

3

或者,如果你不希望添加另一个库,请执行以下操作:

public int hashCode() { 
    StringBuilder builder = new StringBuilder(); 
    builder.append(myString); 
    builder.append(myInteger); 
    return builder.toString().hashCode(); 
} 
3

Eclipse中始终没有大致相同的哈希函数,这是一个有一个在和字符串作为字段

public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + this.interger; 
     result = prime * result + ((this.string == null) ? 0 : this.string.hashCode()); 
     return result; 
    } 

一类,他们总是选择31作为首要的例子,然后通过构建多个哈希函数或者它的原始值。像这样的东西不难作为一种方法来创建。

 public int hashCode(Object ... things) { 
     final int prime = 31; 
     int result = 1; 
     for(Object thing : things) { 
      result = prime * result + thing.hashCode(); 
     } 
     return result; 
    } 
0

继最近的编辑,如果检索速度比存储顾虑更重要,你可以预先计算和构造您StringInt类时存储的哈希码。这是安全的,因为您已将Stringint字段标记为final,并且还确定String是不可变的。

此外,您可以优化您的equals方法,方法是在进行完整比较之前检查比较对象== this。我还建议在比较字符串字段之前先进行比较便宜的基于int的比较。

另一个最后一个建议:你可以改变你valueOf(String, int)方法要么建立一个StringInt或者如果已经有一个具有相同String和INT值存在返回先前创建的实例。这使建设更昂贵,但比较非常便宜,因为您可以使用“==”来比较StringInt,因为知道将不会使用相同的Stringint值创建两个StringInt值。

1

哈希码方法可能被多次调用,因此值得优化。如果计算复杂,则考虑记忆散列值。另外,避免做需要更多计算的事情。 (例如,StringBuilder解决方案大部分时间花费在创建临时字符串上。)

我想指出的另一件事是散列的质量很重要。您希望避免任何映射大量常用密钥的哈希码算法。如果发生这种情况,散列表查找可能不再是O(1)。 (在最坏的情况下,它将是O(N)...即相当于线性搜索!)。这是一个不好的散列函数的例子:

int hashcode() { 
    int hash = 1; 
    for (int val : this.values) { 
     hash = hash * value; 
    } 
    return hash; 
} 

考虑会发生什么如果this.values一个元素是零......

0

您还可以使用Objects类从java.util.Objects包迅速获得哈希码。

@Override 
public int hashCode() { 
    return Objects.hash(this.string, this.integerValue, this.otherDataTypes); 
}