Javaの中のhashCodeの正確な価値を求める方法について話します。

4425 ワード

本論文で研究したのは主にJavaにおけるhashCodeの正確な値を求める方法に関する内容であり、具体的には以下の通りである。
分散リストには最適化があり、対象のハッシュコードをキャッシュすることができます。ハッシュコードが一致しないと、対象の等方性を検査しないで、直接に異なるオブジェクトと見なします。ハッシュコードが等しい場合、オブジェクトが等しいかどうかを検出することができる。
オブジェクトが同じハッシュコード(hashCode)を持つと、彼らは同じハッシュバケツにマッピングされる。ハッシュリストのすべてのオブジェクトのハッシュコードが同じである場合、このハッシュリストは、リンクテーブルに縮退し、クエリ効率を大幅に低減する。
良いハッシュ関数は、通常、「待ちたくないオブジェクトのために、等しくないハッシュコードを生成する」傾向がある。理想的には、ハッシュ関数は、集合中の望ましくないなどの例をすべての可能なハッシュに均等に分布させるべきであるが、この理想を完全に達成するためには非常に困難であり、以下に、比較的簡単で効果的なハッシュ方法を与える。
1.ゼロではない変数、例えば17を、リセットというintタイプの変数に保存します。
2.オブジェクト内の各キードメインf(equals方法に含まれる各ドメインを指す)に対して、以下のステップを実行する。
  • は、このドメインのためにintタイプのハッシュコードc
  • を計算する。
  • bollanタイプであれば、計算(f?1:0)
  • 、このドメインがbyte、char、shotまたはintタイプであれば、(int)f)
  • を計算する。
  • は、ドメインがlongタイプである場合、計算(int)(f^(f>>>32)
  • )を行う。
  • ドメインがfloatタイプであれば、Float.float ToIntBits(f)
  • を計算する。
  • は、ドメインがdoubleタイプである場合、Double.double ToLongBits(f)を計算し、上記のステップで得られたlongタイプの値に従ってハッシュ値
  • を計算する。
  • は、ドメインがオブジェクト参照であり、このクラスのequals方法が再帰的にequalsを呼び出すことによってそのドメインを比較すると、同様にこのドメインについて上記の方法で再帰的にhashCode
  • を呼び出す。
  • は、ドメインが1つの配列であるならば、各要素を個別のドメインとして処理し、これらの原則を再帰的に適用し、配列内の各要素が重要であれば、ARrays.hashCode方法を直接使用することもできる。
  • は、上記のステップで得られたハッシュコードcを、次の式に従って、reultに順次結合する。result = 31 * result + c;   乗算は、より良いハッシュ関数を得るために行われます。例えば、Stringのハッシュ関数が乗算を省略すると、アルファベット順の異なるすべての文字列に同じハッシュコードがあります。ここで31を選択したのは、奇数の素数だからです。乗数が偶数で、乗算がオーバーフローすると情報が失われます。2と乗算するのは変位に等しいからです。素数を使う利点はそれほど明らかではないが、慣習的に素数を使ってハッシュ結果を計算する。31は、乗算の代わりにシフトと減算でより良い性能を得ることができる良い特性がある。現在のVMはこのような最適化を自動的に実現できる。
  • 一つのクラスが可変でない場合(すべてのドメインがfinal修飾であり、すべてのドメインが基本タイプまたは可変ではない)、かつハッシュコードを計算するオーバーヘッドも比較的大きい場合は、ハッシュコードを対象内部にキャッシュすることを考慮すべきである。
    
    public class HashCodeDemo {
      static class HashCodeClass {
        private final boolean bResult;
        private final byte byteValue;
        private final char charValue;
        private final short shortValue;
        private final int intValue;
        private final long longValue;
        private final float floatValue;
        private final double doubleValue;
        private final String str;
        private final int[] arrayValue;
    
        //volatile               ,          
        private volatile int hashCode;
    
        public HashCodeClass() {
          bResult = false;
          byteValue = 1;
          charValue = 'a';
          shortValue = 1;
          intValue = 1;
          longValue = 1l;
          floatValue = 1.0f;
          doubleValue = 1.0d;
          str = getClass().getName();
          arrayValue = new int[] {1,2,3,4,5};
        }
    
        @Override
        public int hashCode() {
          if(hashCode == 0) {
            //           ,          
            int result = 17;
            //       ,                         
            final int HASH_CODE = 31;
            result = HASH_CODE * result + (bResult ? 1 : 0);
            result = HASH_CODE * result + byteValue;
            result = HASH_CODE * result + charValue;
            result = HASH_CODE * result + shortValue;
            result = HASH_CODE * result + intValue;
            result = HASH_CODE * result + (int) (longValue ^ (longValue >>> 32));
            result = HASH_CODE * result + Float.floatToIntBits(floatValue);
            long doubleLongValue = Double.doubleToLongBits(doubleValue);
            result = HASH_CODE * result + (int) (doubleLongValue ^ (doubleLongValue >>> 32));
            result = HASH_CODE * result + (str == null ? 0 : str.hashCode());
            System.out.println("str=" + str + ", str.hashCode=" + str.hashCode());
            result = HASH_CODE * result + arrayValue.hashCode();
            return result;
          } 
          return hashCode;
        }
      }
    
      public static void main(String[] args) {
        HashCodeClass obj = new HashCodeClass();
        System.out.println("obj.hashCode=" + obj.hashCode());
        System.out.println("obj="+obj.toString());
      }
    }
    出力
    
    str=com.demo.test.HashCodeDemo$HashCodeClass, str.hashCode=-205823051
    obj.hashCode=946611167
    str=com.demo.test.HashCodeDemo$HashCodeClass, str.hashCode=-205823051
    obj=com.demo.test.HashCodeDemo$HashCodeClass@386c23df
    締め括りをつける
    以上がJavaの中のhashCodeの正確な価値を求める方法についての内容です。興味のある方は引き続き当駅の他のテーマを参照してください。友達のサポートに感謝します。