2009-07-30 12 views
11

私はEclipseとアイデアが、その属性に基づいてオブジェクトのhashCodeを自動的に作成するこのテンプレートを持っていることを覚えています。文字列とintからハッシュを作成する

数値と文字列を使用する場合の戦略の1つは、このようなものです。

return stringValue.hashCode() + intValue * 32; 

このようなものはありません。

私は日食も考えも持っていないので、このような機能を作りたいと思います。私は、このクラスは、大容量メモリ・マップ(> 10K要素)のためのキーとして使用されることになるこのミニクラスに

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

を作成する回答に基づいて

EDIT

私にはありません文字列とintが同じかどうかを見つけるたびにそれらを繰り返したいと思う。

ありがとうございます。

ps .. mmhおそらく名前はStringIntKeyである必要があります。

+0

オスカー、私は良いクラスだと思います。 hashCodeメソッドは、明確で、信頼性が高く、実行可能です。 文字列がヌルにならないようにするにはどうすればよいですか?あなたのコンストラクタで、nullの場合はNPEをスローします。その後、equalsおよびhashCodeでnullガードを削除できます。 最後に、このような質問には「効果的なJava」のコピーを用意してください。 EclipseとIDEAによって作成されたhashCodeメソッドは、その本をベースにしています。 –

+0

equalsメソッドで、==の代わりに文字列use equalsを比較する必要があります。 –

答えて

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

+0

HashCodeBuilderソースコードはオンラインですか?私はそれを見ます。 – OscarRyz

+0

それは言う:string.hashCode * 37 + intValue !!私のために十分!ありがとうございます – OscarRyz

3

それとも、あなたが別のライブラリを追加したくない場合は次のようなことをしてください:

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

Doh!..時々私はこの種の解決策を見逃す!!他のライブラリを追加したくありません。アドバイスありがとう – OscarRyz

+2

@aperkins: "return(myString + myInteger).hashCode()"と書く方が簡単です。 JavaコンパイラはこれをStringBuilder.append呼び出しの同等のシーケンスにコンパイルします。 –

+2

@perkins:もう一つのことは、スピードが本当に心配なのであれば、このアプローチはコンポーネントのハッシュコードを計算して結合するよりもかなり遅いということです。 –

3

Eclipseが常にほぼ同じハッシュ関数を実行し、ここでの例では、彼らは常に首相として31を選択して、ハッシュ関数でビルドすることにより、複数のフィールド

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

などでと文字列とクラスのためですまたはプリミティブの場合はその値。このようなものは、方法として作るのが難しくありません。あなたの最も最近の編集に

さらに
 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は不変であるため、安全です。

また、完全比較を行う前に、比較するオブジェクトが== thisであることを確認して、equalsメソッドを最適化することができます。また、文字列フィールドを比較する前に、より安価なintベースの比較を行うことをお勧めします。

別の最終提案:あなたはStringIntを構築するか、あなたのvalueOf(String, int)方法を変更したり、1がすでに同じStringとint型の値で存在する場合、以前に作成されたインスタンスを返すことができます。これは、同じStringintの値を持つ2つのStringIntが作成されないという知識の中で、 "=="を使用してStringIntを比較することができるので、建設コストが高くなりますが、非常に安価です。

1

ハッシュコードメソッドは、何度も呼び出される可能性があるため、最適化する価値があります。計算が複雑な場合は、ハッシュ値をメモすることを検討してください。また、必要以上の計算が必要な作業は避けてください。たとえば、StringBuilderソリューションは、ほとんどの時間を一時的なStringの作成に費やします。

もう1つのことは、ハッシュの品質が重要であるということです。たくさんの共通鍵をマップするハッシュコードアルゴリズムを避けたいとします。その場合、ハッシュテーブル参照はもはやO(1)にはなりません。 (最悪の場合、それはO(N)...つまり線形検索と同等です!)。

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

0

また、すばやくハッシュコードを取得するにはjava.util.ObjectsパッケージからObjectsクラスを使用することができます... this.valuesの要素がゼロであれば何が起こるかを考えてみましょう。ここでは悪いハッシュ関数の例を示します。

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