8

次のような単純なカスタム Point クラスがあり、hashCode の実装を改善できるかどうか、またはこれが最善かどうかを知りたいです。

public class Point 
{
    private final int x, y;

    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public int getX() 
    {
        return x;
    }

    public int getY()
    {
        return y;
    }

    @Override
    public boolean equals(Object other) 
    {
        if (this == other)
          return true;

        if (!(other instanceof Point))
          return false;

        Point otherPoint = (Point) other;
        return otherPoint.x == x && otherPoint.y == y;
    }


    @Override
    public int hashCode()
    {
        return (Integer.toString(x) + "," + Integer.toString(y)).hashCode();
    }

}
4

8 に答える 8

10

文字列は使用しないでください。これといくつかの実装 (除算法、乗算法など) の背後には多くの理論があります。約 1 時間あれば、この MIT クラスを見ることができます

そうは言っても、Netbeans 7.1が示唆しているのは次のとおりです。

@Override
public int hashCode() {
    int hash = 7;
    hash = 71 * hash + this.x;
    hash = 71 * hash + this.y;
    return hash;
}

2015 年 10 月 編集

しばらく前に IntelliJ を使い始めましたが、今はもっと幸せに暮らしています。これは、hashCode の自動生成によって生成されるものです。少し冗長です。素数の使用にも注意してください。

@Override
public int hashCode() {
    int result = x;
    result = 31 * result + y;
    return result;
}
于 2012-02-03T21:48:21.783 に答える
5

Gevorg によって提案されているすべての重要なメンバー フィールドの値の手動乗算は、おそらく最も効率的であり、適切な値の分布を持っています。ただし、読みやすさを優先する場合は、Java 7 で利用できる優れた代替手段があります...

import java.util.Objects;

...

@Override
public int hashCode() {
    return Objects.hash(x, y);
}

...またはGuavaライブラリで:

import com.google.common.base.Objects;

....

@Override
public int hashCode() {
    return Objects.hashCode(x, y);
}

これらの varags メソッドは両方ともArrays.hashCode(Object[] a)に委譲するだけなので、int のオートボクシングとオブジェクト参照の配列の作成により、パフォーマンスにわずかな影響がありますが、リフレクションを使用するよりもはるかに重要ではありません。 .

また、ハッシュコードの計算にどのフィールドが使用され、すべての乗算および加算構文が のフードの下に隠されているかを簡単に確認できるため、読みやすさは非常に優れていますArrays.hashCode(Object[] a)

public static int hashCode(Object a[]) {
    if (a == null)
        return 0;

    int result = 1;

    for (Object element : a)
        result = 31 * result + (element == null ? 0 : element.hashCode());

    return result;
}
于 2012-02-03T22:55:30.457 に答える
3

文字列を使用しない、よりシンプルでパフォーマンスの高いメソッドを使用することをお勧めします。おそらく、この回答からのJosh Blochのメソッドです。あなたの場合は、次のようになります。

return 37 * x + y;

編集:nybblerは正しいです。実際に推奨されるのは次のとおりです。

int result = 373; // Constant can vary, but should be prime
result = 37 * result + x;
result = 37 * result + y;
于 2012-02-03T21:34:17.960 に答える
0

既存のPoint型クラスの実装を調べることができます。

/**
343      * Returns the hashcode for this <code>Point2D</code>.
344      * @return a hash code for this <code>Point2D</code>.
345      */
346     public int hashCode() {
347     long bits = java.lang.Double.doubleToLongBits(getX());
348     bits ^= java.lang.Double.doubleToLongBits(getY()) * 31;
349     return (((int) bits) ^ ((int) (bits >> 32)));
350     }

差出人:http ://kickjava.com/src/java/awt/geom/Point2D.java.htm#ixzz1lMCZCCZw

hashCode実装の簡単なガイドはここにあります

于 2012-02-03T21:40:28.427 に答える
0

私は自分のハッシュとequals関数を書いていたので、これを見つけました:)

import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;

@Override
public boolean equals(Object obj) {
   return EqualsBuilder.reflectionEquals(this, obj);
 }
@Override
public int hashCode() {
   return HashCodeBuilder.reflectionHashCode(this);
 }

もちろん、次の点に注意してください。

リフレクションには動的に解決される型が含まれるため、特定のJava仮想マシンの最適化を実行できません。その結果、リフレクティブ操作は非リフレクティブ操作よりもパフォーマンスが遅くなり、パフォーマンスに敏感なアプリケーションで頻繁に呼び出されるコードのセクションでは回避する必要があります。SRC

于 2012-02-03T21:34:17.837 に答える
0

デフォルトでは、Eclipse は Point クラスに次のような hashCode() 関数を使用します。

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + getOuterType().hashCode();
    result = prime * result + x;
    result = prime * result + y;
    return result;
}

少なくとも、素数を hashCode アルゴリズムに組み込むと、その「一意性」に役立ちます。

于 2012-02-03T21:41:39.690 に答える
0

JDK の Point クラスから (Point2d から継承):

public int hashCode() {
    long bits = java.lang.Double.doubleToLongBits(getX());
    bits ^= java.lang.Double.doubleToLongBits(getY()) * 31;
    return (((int) bits) ^ ((int) (bits >> 32)));
}

それはあなたの実装よりも少し良く見えます。

于 2012-02-03T21:36:35.483 に答える