2017-11-23 11 views
1

この質問はかなり素人ですが、同じオブジェクトインスタンスをキーとして使用すると、ハッシュマップが値を格納または取得しない理由を理解できません。 。私のコードは次のとおりです。ハッシュコードをオーバーライドしても両方の値が取得されない同じオブジェクトのハッシュコード&イコールを

public class Candidate { 

    private String id; 
    private String name; 

    public Candidate (String id, String name){ 
     this.id = id; 
     this.name = name; 
    } 

    public static void main(String args[]){ 
     Candidate cad = new Candidate("101","hari"); 

     HashMap<Candidate,String> mp = new HashMap<Candidate,String>(); 
     mp.put(cad, "sachin"); 
     mp.put(cad, "shewag"); 

     for(Candidate cand : mp.keySet()){ 
      System.out.println(mp.get(cand).toString()); 
     } 
    } 

私は以下のようにハッシュコードをオーバーライドしています。

@Override 
    public boolean equals(Object obj){ 
     Candidate cad =(Candidate)obj; 
     if(!(obj instanceof Candidate)){ 
      return false; 
     } 
     if(cad.id.equals(this.id) && cad.name.equals(this.name)){ 
      return true; 
     } 
     return false; 
    } 

    @Override 
    public int hashCode(){ 
     return Objects.hash(id, name); 
    } 

ハッシュマップのサイズを取得しようとすると、1つのみとして返されます。つまり、ハッシュマップへの最初の挿入は、2番目の挿入によってオーバーライドされました。

私は2つの値を挿入するために候補の同じインスタンスを使用しているからですか?両方のキー、値のペアを挿入するようにハッシュマップを強制することは可能ですか?

+3

サイドノートでは、このキャスト '候補CAD =(候補者)は、obj;'前のチェックに'obj instanceof Candidate'は、待っている' ClassCastException'のようです。 –

答えて

3

マップの背後にある考え方は、1)キーがユニーク - 特定のキーに対して1つのキー/値ペアを保持し、2)ルックアップが比較的安価であるということです。

あなたはHashMap内に1つのオブジェクトしか持っていません。マップに別のキー、値ペアを追加すると、キーがマップの前のアイテムと同じ場合は、前のアイテムはで置き換えられ、新しいアイテムはに置き換えられます。 2つ以上の項目を追加する場合は、別のキーを使用するか、List<...>のオブジェクトを値として持つMapを作成します。例えば、このような状況で

HashMap<Candidate, List<String>> 

、あなたは最初のマップは、候補アイテムを保持しているかどうかを確認するだろう、そうであれば、そのリストに新しい文字列を追加します。そうでない場合は、新しいArrayList<String>値を持つ新しい候補を追加します。通常、私はちょうどこの目的のためにメソッドを使用し、何かのように:

public static void put(Candidate cand, String text) { 
    if (newMap.containsKey(cand)) { 
     newMap.get(cand).add(text); 
    } else { 
     List<String> list = new ArrayList<>(); 
     list.add(text); 
     newMap.put(cand, list); 
    } 
} 

そして、はい、コメントでd.j.brown状態として、クラスキャスト例外を回避するためにあなたのequalsメソッドを修正。

そうような何か:

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Objects; 

public class MyCandidateTest { 
    private static Map<Candidate, List<String>> newMap = new HashMap<>(); 

    public static void main(String args[]) { 
     Candidate cad = new Candidate("101", "hari"); 

     put(cad, "Foo"); 
     put(cad, "Bar"); 

     for (Candidate cand : newMap.keySet()) { 
      System.out.println(newMap.get(cand).toString()); 
     } 
    } 

    public static void put(Candidate cand, String text) { 
     if (newMap.containsKey(cand)) { 
      newMap.get(cand).add(text); 
     } else { 
      List<String> list = new ArrayList<>(); 
      list.add(text); 
      newMap.put(cand, list); 
     } 
    } 

} 

public class Candidate { 

    private String id; 
    private String name; 

    public Candidate(String id, String name) { 
     this.id = id; 
     this.name = name; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     // Candidate cad =(Candidate)obj; // !! no 
     if (!(obj instanceof Candidate)) { 
      return false; 
     } 
     Candidate cad = (Candidate) obj; // !! yes 
     if (cad.id.equals(this.id) && cad.name.equals(this.name)) { 
      return true; 
     } 
     return false; 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hash(id, name); 
    } 
} 
+0

マップに文字列のリストを追加するか、同じ値を持つ別のインスタンスを作成します。私はこの解決策が働くことを知っているしかし、hashmapに同じキーを持つ2つの値を格納する方法はありますか?ハッシュコードの目的は何ですか? – user1734698

+0

@ user1734698 **いいえ**、それは最初の場所で 'HashMap'のポイントです – Eugene

+0

@Eugene:それがありました! – user1734698

2

、ところでjava-8であなたが望むものを単純化した例を行うための簡単な方法があります:

HashMap<String, List<String>> mp = new HashMap<>(); 

    List<String> list = Arrays.asList("aa", "aa", "bb", "bb"); 

    for (String s : list) { 
     mp.computeIfAbsent(s, k -> new ArrayList<>()).add("c"); 
    } 

    System.out.println(mp); // {bb=[c, c], aa=[c, c]} 
関連する問題