从string和int创建哈希

时间:2009-07-30 21:57:14

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

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

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

  return stringValue.hashCode() + intValue * 32;

Ooor之类的东西。

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

修改

基于答案,我创建了这个迷你级

    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。

6 个答案:

答案 0 :(得分:8)

使用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

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

哈希码方法可能被多次调用,因此值得优化。如果计算很复杂,请考虑记住哈希值。此外,避免做一些需要更多计算的事情。 (例如,StringBuilder解决方案花费大部分时间创建临时String。)

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

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

考虑如果this.values的元素为零...

会发生什么

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

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

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

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