1

この場合、ルールと呼ばれるオブジェクトのリストがあります。このオブジェクト自体は、システムでルールを複製できないため、ハッシュコード比較を行う必要があるフィールドのリストです。

つまり、フィールド A と B を持つ 2 つのルール R1 と R2 があるとします。

ここで、R1 の A と B の値がそれぞれ 7 と 2 の場合。

R2 ではそれぞれ 3 と 4 であり、ハッシュコード比較であるシステム内のルールの重複をチェックするために使用したプロセスは失敗します

私が使用した方法は

for(Rule rule : rules){
changeableAttrCode=0;

fieldCounter=1;

attributes = rule.getAttributes();

for(RuleField ruleField : attributes){

changeableAttrCode = changeableAttrCode + (fieldCounter * ruleField.getValue().hashCode());

fieldCounter++;

}
parameters = rule.getParameters();

for(RuleField ruleField : parameters){

changeableAttrCode = changeableAttrCode + (fieldCounter * ruleField.getValue().hashCode());

fieldCounter++;

}

changeableAttrCodes.add(changeableAttrCode);

ここにすべてのルールのハッシュコードを格納する changeableAttrCodes があります。

システム内のルールの重複が見られるだけでなく、この種の問題が今後発生しないように、より良い方法を提案してください。

前もって感謝します

4

5 に答える 5

5

hashcode()等しいかどうかを確認するために使用することを意図したものではありません。return 42;の完全に有効な実装ですhashcode()。rules オブジェクトを上書きしてequals()(さらに言えばhashcode())、それを使用して 2 つのルールが等しいかどうかを確認してみませんか? 2 つのオブジェクトは常に同じハッシュコードを持つ必要があるため、調査が必要なオブジェクトを確認するためにハッシュコードを使用することもできますがequal()、これはシステムによって必要な場合と必要でない場合があるパフォーマンスの向上です。

于 2010-02-25T11:00:05.363 に答える
4
  • クラス Rule で実装hashCodeします。equals
  • の実装でequalsは、その値を比較する必要があります。

次に、 a を使用しHashSet<Rule>て尋ねるif(mySet.contains(newRule))

HashSet + equals の実装は、ハッシュの非一意性の問題を解決します。分類と速度のためにハッシュを使用しますが、最後に equals を使用して、同じハッシュを持つ 2 つのルールが同じルールであるかどうかを確認します。

ハッシュの詳細: 手動で行う場合は、素数の提案を使用し、文字列ハッシュコードの JDK コードを確認してください。クリーンな実装を作成したい場合は、要素のハッシュコードを取得しようとし、ある種の int の配列を作成し、Arrays.hashCode(int[]) を使用してそれらの組み合わせのハッシュコードを取得します。

于 2010-02-25T11:00:50.603 に答える
3

更新されたハッシュアルゴリズムは、ハッシュ値の適切な広がりを生成していません-(7, 2) と (3, 4) に同じ値を与えます:

1 * 7 + 2 * 2 = 11
1 * 3 + 2 * 4 = 11

また、(11, 0)、(-1, 6)、... に対しても同じ値が得られ、現在のアルゴリズムに基づいて、無限の数の同様の等価クラスを自明に構成できます。

もちろん、衝突を避けることはできません。インスタンスが十分にある場合、ハッシュの衝突は避けられません。ただし、衝突の可能性を最小限に抑えることを目指す必要があります。優れたハッシュ アルゴリズムは、ハッシュ値を広範囲の値に均等に分散するように努めます。これを実現する一般的な方法は、 n 個の独立したフィールドを含むオブジェクトのハッシュ値を、個々のフィールドの異なるハッシュ値を保持するのに十分な大きさの基数を持つn桁の数値として生成することです。

あなたの場合、乗算する代わりにfieldCounter、素数定数、たとえば 31 を乗算する必要があります (これは数値の基数になります)。そして、結果に別の素数定数を追加します (例: 17)。これにより、ハッシュ値の分散が改善されます。(もちろん、具体的なベースは、フィールドが取り得る値に依存します-それについての情報はありません。)

また、 を実装するhashCode場合は、同様に実装することを強くお勧めしequalsます。実際、後者を使用して同等性をテストする必要があります。

実装hashCodeに関する記事はこちら。

于 2010-02-25T10:59:49.477 に答える
2

あなたがここで何をしようとしているのか理解できません。ほとんどのハッシュ関数のシナリオでは、可能なハッシュ値よりもハッシュするオブジェクトの方がはるかに多いため、衝突は避けられません (鳩の巣の原理です)。

通常、2 つの異なるオブジェクトが同じハッシュ値を持つ場合があります。ハッシュ関数だけに頼って重複を排除することはできません。

一部のハッシュ関数は衝突を最小限に抑える点で他よりも優れていますが、それでも避けられません。


そうは言っても、通常は十分なハッシュ関数を提供するいくつかの簡単なガイドラインがあります。Joshua Bloch は、著書『Effective Java 2nd Edition』で次のように述べています。

  • intと呼ばれる変数に、ゼロ以外の一定値、たとえば 17 を格納しますresult
  • 各フィールド のintハッシュコードを計算します。c
    • フィールドが の場合boolean、計算します(f ? 1 : 0)
    • フィールドが の場合byte, char, short, int、計算します(int) f
    • フィールドが の場合long、計算します(int) (f ^ (f >>> 32))
    • フィールドが の場合float、計算しますFloat.floatToIntBits(f)
    • フィールドが の場合はdouble、computeDouble.doubleToLongBits(f)を実行し、結果を上記のようにハッシュlongします。
    • フィールドがオブジェクト参照であり、このクラスのequalsメソッドが を再帰的に呼び出してフィールドを比較する場合は、フィールドに対して を再帰的に呼び出しequalsますhashCode。フィールドの値が の場合、null0 を返します。
    • フィールドが配列の場合は、各要素が個別のフィールドであるかのように扱います。配列フィールドのすべての要素が重要な場合はArrays.hashCode、リリース 1.5 で追加されたメソッドのいずれかを使用できます。
  • ハッシュコードcresult次のように結合します。result = 31 * result + c;
于 2010-02-25T10:59:53.167 に答える
0

私は、あなたが望むものを達成できる唯一の方法はPerfect Hashingを使用することだと書き始めました。

しかし、システム内でオブジェクトを複製することはできないとあなたが言ったという事実について考えました。

helios からの示唆に富むコメントに基づいて編集します。

あなたの解決策は、「ルールを複製できない」と書いたときの意味によって異なります。

文字通りできない、つまり特定の値のセットを持つルールのインスタンスが 1 つだけ存在することが保証されていることを意味している場合、問題は簡単です。ID 比較を実行できます。その場合、== を使用して ID 比較を実行できます。 .

一方、何らかの理由(パフォーマンス)ですべきではないことを意味していた場合、問題も簡単です。値の比較を行うだけです。

問題をどのように定義したかを考えると、ハッシュコードを平等の代わりに使用することを検討すべきではありません。他の人が指摘しているように、ハッシュコードはその性質上、完全ハッシュソリューション に行かない限り、衝突 (偽の等値) を引き起こしますが、この場合、なぜそうするのでしょうか?

于 2010-02-25T12:35:37.457 に答える