【问题标题】:Create hash from string and int从字符串和整数创建哈希
【发布时间】:2010-11-15 15:05:36
【问题描述】:

我记得eclipse和idea都有这个模板可以根据属性自动创建对象的hashCode。

如果使用数字和字符串,其中一种策略是这样的。

  return stringValue.hashCode() + intValue * 32;

类似的东西。

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

编辑

根据答案我创建了这个迷你班

    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。

【问题讨论】:

  • 奥斯卡,我认为这是一堂好课。 hashCode 方法清晰、可靠且高效。如何防止字符串为空?在您的构造函数中,如果 NPE 为空,则抛出一个 NPE。然后你可以删除那些在 equals 和 hashCode 中的空保护。最后,为此类问题保留一份“Effective Java”副本。 Eclipse 和 IDEA 创建的 hashCode 方法就是基于那本书。
  • 在你的equals方法中应该比较字符串使用equals而不是==。

标签: java eclipse hash code-generation intellij-idea


【解决方案1】:

使用 Apache Commons HashcodeBuilder:

public int hashCode() {
    new HashCodeBuilder(17, 37).
           append(myString).
           append(myInt);
}

链接在这里: http://commons.apache.org/lang/api-2.3/org/apache/commons/lang/builder/HashCodeBuilder.html

这里:

http://www.koders.com/java/fidCE4E86F23847AE93909CE105394B668DDB0F491A.aspx

【讨论】:

  • HashCodeBuilder源码在线吗? ... .我会看的。
  • 它说:string.hashCode * 37 + intValue!!对我来说够多的了 !!谢谢
【解决方案2】:

Eclipse 总是做大致相同的散列函数,这里是一个类的例子,其中一个 in 和 String 作为字段

    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;
     }

【讨论】:

    【解决方案3】:

    您也可以使用java.util.Objects包中的Objects类快速获取哈希码。

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

    【讨论】:

      【解决方案4】:

      或者,如果您不想添加其他库,请执行以下操作:

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

      【讨论】:

      • Doh!.. 有时我会想念这种解决方案!是的,我不想添加另一个库。感谢您的建议
      • @aperkins:只写“return (myString + myInteger).hashCode()”更简单。 Java 编译器会将其编译为等效的 StringBuilder.append 调用序列。
      • @perkins:另外一件事,如果你真的关心速度,那么这种方法比计算和组合组件哈希码要慢得多。
      • hashCode 应该很快,最好取字符串的 hashCode 并对整数进行简单的整数数学运算。
      • 速度问题可能是真的,但是我从未注意到在我们编写的代码中使用这种方法会显着降低速度。通常我们的性能问题更多地与电汇或算法更改有关。
      【解决方案5】:

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

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

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

      考虑如果this.values 的元素为零会发生什么...

      【讨论】:

        【解决方案6】:

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

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

        另一个最终建议:您可以更改 valueOf(String, int) 方法以构造 StringInt 或返回先前创建的实例(如果已存在具有相同 String 和 int 值的实例)。这使得构建更加昂贵,但比较非常便宜,因为您可以使用“==”比较 StringInts,因为知道永远不会创建具有相同 Stringint 值的两个 StringInts。

        【讨论】:

          猜你喜欢
          • 2020-06-05
          • 2017-04-04
          • 1970-01-01
          • 2013-05-02
          • 1970-01-01
          • 2016-07-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多