2011-07-06 1 views
1

私はこの不思議な問題にぶち込んでいます。質問ごとに各回答から回答を得ようとすると、ハッシュマップから回答を得るとnullが返される場合を除き、ほとんどの回答が正しく取得されます。私はeclipseでデバッグモードを実行し、その値をhashmap getAnswerMap()から取得しようとすると、そのハッシュマップ内の値を取得しようとすると、両方が正確に同じように見える質問を比較しました。Hashmapは、存在するオブジェクトを取得しようとするとNullを返します。

 
for (SurveyResponse response : responses) { 
     MultipleChoiceAnswer answer = (MultipleChoiceAnswer) response.getAnswerMap().get(question); 
     .... 
     .... 
     } 

はその後、私はそれがハッシュコードの問題であると思ったので、私はハッシュコードをチェックするためのコードの別の醜い行を追加して、彼らは実際には同じハッシュコードと追加の次の行には、働いていると正しく答えを設定しました。

 
for (SurveyResponse response : responses) { 
     MultipleChoiceAnswer answer = (MultipleChoiceAnswer) response.getAnswerMap().get(question); 
     for (Entry entry: response.getAnswerMap().entrySet()) { 
     if (entry.getKey().hashCode() == question.hashCode()) answer = (MultipleChoiceAnswer) entry.getValue(); 
     .... 
     .... 
     } 

しかし、これは非常に醜いです。私は本当にハッシュマップから正しく答えたいと思います。助言がありますか?

更新: hashCode()メソッドとequals()メソッドの両方を両方のオブジェクトで呼び出すと、両方とも同等のハッシュコードがあり、equals()がtrueを返すことが示されます。私は、解答の1つが示すように、質問がハッシュマップに挿入されたときに別のハッシュコードで挿入されている可能性があると考えています。したがって、取得しようとしているオブジェクトに古いものと同じハッシュコードがないため、問題のgetメソッドを呼び出すとnullが返されます。非常に有用な答えのみんな!

+0

あなたがしたいですかあなたのhashCode()とequals()を共有するには? –

答えて

3

一つのことに動作するHashMapための要件である:あなたがキーとして使用しているクラスが不変であることを確認します - それ以外の場合は、キーを置くと1つのキーにハッシュされますが、取り出したときには別のキーになります。

編集:に変更できませんが、ハッシュコードを変更しない方法でのみ変更できます。オブジェクト全体を不変にすることは、それを行う最も簡単な方法ですが、それだけではありません。 hashCode() sが同じである場合、あなたは彼らがそのequals()に一致しているhashCode()equals()をオーバーライドする必要がHashMapと100%、確定キーが常にtrueを返すオブジェクトを作るために

+0

私はこれがなぜdownvoteを得たのか分かりません、私達が知っているすべてのために、それは問題への解決であるかもしれません。 – biziclop

+1

はい、いいえ - ハッシュコードは同じにしておかなければなりませんが、オブジェクトを変更することは、以前と同じ*論理的*同じオブジェクトであれば、必ずしもそのハッシュコードを変更する必要はありません。たとえば、 'User'クラスを取ってください。例えば、各ユーザが一意のID番号を持っていれば、完全なハッシュコードになります。しかし、例えば、ユーザのID番号(すなわち、ハッシュコード)は、パスワードを変更するだけで変更する必要はない。(記録のために、私はダウンボートしなかった)。 – Mac

+0

@Mac Trueですが、あなたのハッシュコードがフィールドを最終的に形成することを宣言することは、まだ良い考えです。コードをメンテナンス可能に保つのに役立ちます。 – biziclop

0

それはあなたが正しくequals(..)をオーバーライドしていない可能性があります - 気を付けるように正しく

+0

私はただのSystem.out.printlnであることを確認し、entry.getKey()。等号(質問)がtrueを返し。 – Sam

1

。ここで

は、IBM developerWorksのブライアン・ゲッツから古いarticleですが、内容は今日でも適用されます。

オーバーライドが等しいのはなぜ()とhashCode()? Integerが オーバーライドequals()hashCode()なかった場合に何が起こるか

Integer をキーとして、HashMapまたは他の ハッシュベースのコレクションで使用したことがない場合は、何もありません。我々 は のために、このようなIntegerオブジェクトを使用していた場合は、HashMapの中の鍵は、我々は確実に我々は我々として get()コールに まったく同じIntegerインスタンスを使用していない限り、 関連付けられた値を取得することが ではないでしょうput() コールでした。これは、我々は唯一の 私たちのプログラム全体 特定の整数値に対応する Integerオブジェクトの単一のインスタンスを使用 ことを確実にすることが必要となります。言うまでもなく、この アプローチが不便と エラーが発生しやすくなります。

インターフェース契約Objectため

は、二つのオブジェクトが equals()に従って等しい場合、それらは同じ hashCode()値を有していなければならないことを要求します。なぜ私たちのルート オブジェクトクラスは、その 識別能力が完全 equals()のそれに包含されている場合、 hashCode()を必要とするのか? hashCode() 方法は、効率のために純粋に存在します。このよう Hashtableとして 、 HashMap、および HashSet - - Javaプラットフォーム アーキテクトは、ハッシュベースのコレクションクラスの重要性 予想される典型的なJavaの アプリケーションでは、と equals()で 多くのオブジェクトと比較すると、 計算コストが高くなることができます。 hashCode() は、効率的なストレージおよびハッシュベース コレクションを使用 検索を可能にするすべてのJavaオブジェクト支持体を有します。

class Question { 

    // ... 


    public boolean equals(Question q) { 
     // do intelligent comparison 
    } 

    public int hashCode() { 
     // calculate hash code 
    } 

} 

しかし、ここであなたが本当にObjectからequals(Object)方法をオーバーライドしますが、単純にはありません:あなたはこの1つのようなequalsメソッドを持っている

+0

ええ、私はあなたの言うことに完全に同意します。しかし、questionとentry.getKey()に対してequals()とhashCode()の両方をチェックしていて、どちらも一貫しています。 – Sam

+0

しかし、hashCodeはオブジェクトがマップに置かれたときと同じです! – Affe

+0

"hashCode()が同じである場合、equals()は常にtrueを返します。" - 実際は記事の状態と同じですが、それは真ではありません。 2つの異なるオブジェクトが同じハッシュコードを持ち、equalsに対してfalseを返す場合、これは完全に有効な実装になります。ハッシュコリジョンが可能です。 – Voo

2

もう一つのガラス玉の推測をそれの横に新しいものを宣言してください。 HashMapはあなたの新しいメソッドについて何も知らないので、マップ内のキーオブジェクトを照会キーと比較するためのオリジナルのメソッドを呼び出します(一致するhashCodeを持つものを見つけた後)。

代わりに、次のようにメソッドを宣言します。

@Override 
    public boolean equals(Object o) { 
     if(! (o instanceof Question)) 
      return false; 
     Question q = (Question)o; 
     // do intelligent comparison 
    } 

(。@Override注釈は、あなたが本当にただ新しいものを作成していない、ここでメソッドをオーバーライドしているコンパイラのチェックをすることができます)

+2

「@ Override」アノテーションを使用すると、コンパイラは「やあ、あなたがオーバーライドしていると思われるメソッドを実際にオーバーライドしているわけではありません! – MatrixFrog

+0

@MatrixFrog:良い点。 –

+1

IntellijのIDEサポートは、Eclipseでも、定型句を手助けするのに非常に優れていると思います。そしてそれはこの種の髪を引っ張る間違いをしません。 –

関連する問題