2016-12-14 2 views
0

現在マップエディターでTDゲームを行っています。今や明らかに、これらのマップを保存して読み込むことができます(または少なくともできるはずです)。 問題:ある時点でHashMap.get()と呼んでいます。残念ながら、私の以前のGoogleの調査によると、.equalsメソッドをオーバーライドするだけでは、まだ異なるハッシュが返されるため、(論理的に)同じである必要があるキーは同じオブジェクトではありません(参照の点で)。 .hashCode()(私が確認したところ、別のハッシュを返しますが、.equalsはtrueを返します)。
"hashCode()"のおかげで、HashMap.get()が適切な値を返しません。

は具体的には、HashMapをキーとして私のクラスPathのインスタンスが含まれており、返す必要があります(HashMap.get(key)のjavadocが唯一、彼らが同じでなければならないと述べているので、サイドノートでは、それは、かなり混乱します)対応する敵のリスト(=値)。

(などゲッターなし)Pathの短いバージョン:

public class Path 
{ 
    private List<Tile> tiles = new ArrayList<>(); 
    @Override 
    public boolean equals(Object obj) { 
     //code comparing the two paths 
    } 
    @Override 
    public int hashCode() { 
     //what I still need to implement. ATM, it returns super.hashCode() 
    } 
} 

public class Tile 
{ 
    private int x; 
    private int y; 
    //constructor 
    //overrides equals 
    //getters & some convenience methods 
} 

2つのパスが等しい場合HashMapは正しいリストを返すように、今、私は、彼らが同じハッシュコードを返したいのですが敵。 (2つの同一のパスを追加することはできません)。

は今、私の質問:

はあなたが私はハッシュを計算する私の独自の実装を記述するハッシュ

  • 、または他の
  • 何か
  • を生成するために、いくつかの外部ライブラリを使用して

    1. を示唆してください。

    HashMapを他のタイプのマップに変更しないようにしてください。問題が解決される場合にも役立ちます。

    +1

    generellの 'IDE'または' IDE'を使用して 'hashcode'を生成させる可能性があります – SomeJavaGuy

    +1

    あなたはハッシュコードを好きなだけ単純または複雑にすることができます。これは、「これらの2つの曖昧なsimliar」チェックをすばやく実行することを意味します。ハッシュコードチェックで生き残ったものに対して、equalsメソッドに入る前にできるだけ多くの致命的に異なるマッチを削除します。だから、あなたのシステムによっては、 'return tiles.size()'が適切かもしれません!追加する価値がある –

    +2

    :人々が間違っているのは、「ハッシュコード」を過度に複雑にすることです。それが実際の 'equals'メソッドと同じように複雑になるのであれば、それを持つことはできません。私は言ったように:それは "クイックチェック"の意味です。 –

    答えて

    1

    Listは、好都合にはlist.hashCode()とも呼ばれる有用な方法を有する。これは、リスト内のすべての要素のhashCodeを計算します。したがって、TileのhashCodeを実装する必要があります。このハッシュコードはおそらくいくつかのプリミティブなフィールドなどで構成されています。

    @Override 
        public int hashCode() { 
         return tiles != null ? tiles.hashCode() : 0; 
        } 
    

    ドキュメントhere

    このリストのハッシュコード値を返します int型のhashCode()
    を参照してください。リストのハッシュコードは、次の計算の結果であると定義される:

    int hashCode = 1; 
        for (E e : list) 
         hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); 
    

    これはlist1.equals(list2)が意味することを確実に一般規約によって要求される、任意の2つのリスト、list1list2list1.hashCode()==list2.hashCode()Object.hashCode()である。

    +0

    'Tile'は実際には非常にプリミティブなので、(上記のように)2つの整数値を保存するだけです。 list.hashCode()についてのヒントをありがとう! – PixelMaster

    +0

    最初のコードブロックは[Objects.hashCode(tiles)]に短縮できます(http://docs.oracle.com/javase/8/docs/api/java/util/Objects.html#hashCode-java.lang .Object-)。 – VGR

    2

    hashCodeは、equalsと一貫して実装する必要があります。 IDEはよくhashCodeequalsを生成するまともな仕事を行います。また、Objects.equals(...)Objects.hash(...)と考えてください。

    のキーとしてPathをキーとして使用することに関する1つの警告。クラスを不変にして、確実に動作させる必要があります。または少なくとも、キーのhashCodeが変更されていないことを確認してください。さもなければ、同じか等しいキーであってもデータを返すことができないかもしれません。

    +0

    の 'Path'の不変性について:私はそれをする必要はないと思っています。通常は、参照を介して取得されたパスを使って' .get'を呼び出します。このエラーは、以前に作成されたマップをロードした後にのみ発生します。 – PixelMaster

    +1

    @ Misteradi1パスのハッシュコードが変更された場合、キーと同じ*インスタンスでもハッシュマップからデータを取得することはできません。ハッシュマップは再びキーのハッシュコードを取得し、それを使用してバケットの値を探します。ハッシュコードが変更された場合、正しいバケットは見つかりません。たとえキーが非常に同じインスタンスであっても。それに注意してください。 – lexicore

    関連する問題