3

コンストラクターが4つの整数フィールドを受け取るXオブジェクトがあります。ハッシュ関数を計算するには、単純に配列に入れてArrays.hashCodeを使用します。

現在、コンストラクターはプライベートであり、静的クリエーターメソッドがあります。以前に呼び出された4つの整数パラメーターを使用してcreatorメソッドが呼び出されるたびに、前回と同じオブジェクトを返すことができるように、構造をメモしたいと思います。[理想的には、比較するために別のXオブジェクトを作成する必要はありません。]

もともとhashSetを試しましたが、hashSet。に等しいオブジェクトが含まれているかどうかを確認するために新しいXを作成する必要がありました...hashSetから「取得」できないという事実を気にしないでください。

私の次のアイデアは、マップするHashTableを使用することです:4つのフィールドのint配列のhashCode->オブジェクト。理由はわかりませんが、それは正しくありません。あまりにも多くの作業をしているように感じますが、hashCodeのポイントは、同じhashCodeに計算される一連のオブジェクトへの一種のマッピングではありませんか?

アドバイスありがとうございます。

4

3 に答える 3

3

一般に、ハッシュ コードの目的は、特定のオブジェクトを探す場所を絞り込むことです。別の言い方をすれば、2 つのオブジェクトが同じハッシュ コードを持つ場合、それらが同じオブジェクトである可能性が「非常に高い」ように、ハッシュ コードを作成するという考え方です。

ここで、「非常に可能性が高い」の可能性は、基本的にハッシュ コードの幅 (ビット数) と品質に依存します。32 ビットのハッシュ コードを使用する Java の場合、この「可能性が非常に高い」とは、一般的に、「オブジェクト データの実際の比較をなくすことができるほど 100% に近くない」ことを意味します。したがって、hashCode() を実装するだけでなく、Java マップ (HashMap など) のキーとして使用されるオブジェクトに equals() を実装する必要があります。

または別の言い方をすれば、多くの作業を行っているように見えても、実装は本質的に正しいということです。要するに、探しているのがパフォーマンスの向上である場合は、毎回新しいオブジェクトを作成するだけでよいということです。ただし、機能的に、特定の値のセットを持つオブジェクトが複数存在しないことが必要な場合、実装は本質的に正しいです。

原則としてできること:

  • 多数の int がある場合、hashCode() については、それらの 2 つの「サンプル」からハッシュ コードを形成するだけです。アイデアは、「選択肢を絞り込む」か、「公平に、しかしそうではない」にすることです。等しいハッシュコードは等しいオブジェクトを意味する可能性が 100% あります。つまり、equals() を実行してチェックする必要があるため、hashCode() と equals() の両方のすべての値を循環させる意味はほとんどありません。
  • より強力なハッシュ コードを使用できる可能性があるため、文字どおり、等しいハッシュ コードは等しいオブジェクトを意味すると見なすことができます。実際には、ハッシュ コード関数ですべての値を 1 回循環し、equals 関数はまったくありません。実際には、これは少なくとも強力な 64 ビット ハッシュ コードを使用することを意味します。あなたが言及した場合には、おそらくそれだけの価値はありません。しかし、それがどのように機能するかについて少し理解したい場合は、Java でのハッシュ コードの高度な使用について書いたチュートリアルを参照してください。
于 2012-11-25T06:27:34.180 に答える
1

構築中の 4 つの整数が結果のオブジェクトがまったく同じであることを意味する場合は、ハッシュではなく、それらをキーとして使用します。完全なオブジェクトをキーとして使用しているのではなく、4 つの整数値のみを使用していることに注意してください。以下の MyObjectSpecification は小さなオブジェクトになります。

public class MyObjectSpecification {
    private final int i1, i2, i3, i4;

    public MyObjectSpecification(int i1, int i2, int i3, int i4) {
        this.i1 = i1;
        this.i2 = i2;
        this.i3 = i3;
        this.i4 = i4;
    }

    public boolean equals(Object o) {
        // ...
    }

    public int hashCode() {
        // ...
    }
}

public class MyObject {
    private static final Map<MyObjectSpecification, MyObject> myObjects
            = new ConcurrentHashMap<MyObjectSpecification, MyObject>();

    private MyObject(MyObjectSpecification spec) {
        // ...
    }

    public static MyObject getMyObject(int i1, int i2, int i3, int i4) {
        MyObjectSpecification spec = new MyObjectSpecification(i1, i2, i3, i4);

        if (myObjects.containsKey(spec)) {
            return myObjects.get(spec);
        }

        MyObject newObject = new MyObject(spec);
        myObjects.put(spec, newObject);
        return newObject;
    }
}
于 2012-11-25T07:34:56.157 に答える
0

Hashtable をどのように使用する予定かはわかりませんが、以下でうまくいくと思います。

    private static Hashtable<Integer, MyObject> objectInstances = 
             new Hashtable<Integer, MyObject>();


    public static MyObject instance(int i1, int i2, int i3, int i4){
         int hashKey = Arrays.hashCode(new int[]{i1, i2,i3,i4});
         //get the object from hashtable
         MyObject myObject = objectInstances.get(hashKey);

         //if object was not already created, create now and put in the hashtable
         if(myObject == null){
           myObject = new MyObject(i1,i2,i3,i4);
           objectInstances.put(hashKey, myObject);
         }
        return myObject;
    }
于 2012-11-25T06:22:57.097 に答える