2

重複するキーが挿入されている場合、JavaHashMapに関して非常に基本的な疑問がありました。

私の意図は、4つのEmpオブジェクトを作成することです。2オブジェクト(e1とe2)は同じhashCodeを持っています。したがって、e1(e2の後に挿入されている)を挿入すると、ハッシュマップは同じハッシュ値を持つオブジェクト(オブジェクトe2)がすでに存在していることを認識します。次に、スロット内のすべてのオブジェクトのキーを同じハッシュ値と比較します。キーが一致するオブジェクトが見つかった場合(以下のEmpクラスのequalsメソッドを呼び出すことにより)、古い値が新しい値に置き換えられます。

以下のテストコードをご覧ください。

import java.util.Map;
import java.util.HashMap;
import java.util.Set;

class Emp {
        String name;
        int age;

        public Emp(String name, int age) {
                this.name = name;
                this.age = age;
        }

        public boolean equals(Object s) {
                if(s instanceof Emp) {
                        Emp s1 = (Emp) s;
                        return ((s1.name.compareToIgnoreCase(this.name) == 0));
                }
                return false;
        }

        public int hashCode() {
                //return (this.name.hashCode() + this.age);
                return this.name.hashCode();
        }
}

public class HashTest {
        public static void main(String[] args) {
                Emp e1 = new Emp("Terry", 26);
                Emp e2 = new Emp("Terry" , 60);
                Emp e3 = new Emp("John", 21);
                Emp e4 = new Emp("Test", 60);

                Map<Emp,Emp> emp = new HashMap<Emp, Emp>();
                emp.put(e2,e2);
                Emp v2 = emp.put(e1,e1);
                emp.put(e3,e3);
                emp.put(e4,e4);

                System.out.println("Replaced Record Name: " + v2.name + " , age: " + v2.age);
                for(Emp e: emp.keySet())
                        System.out.println("Name: " + e.name + " , age: " + e.age);
        }
}

私が期待していた出力: 置換されたレコード名:Terry、年齢:60 名前:テスト、年齢:60 名前:Terry、年齢:26 名前:John、年齢:21

私が得た出力: 置換されたレコード名:テリー、年齢:60 名前:テスト、年齢:60 名前:テリー、年齢:60 名前:ジョン、年齢:21

(Terry、60)が(Terry、26)オブジェクトに置き換えられることを期待していました。これは、Replaced Record Name:Terry、age:60を出力として取得したときに発生しているようです。ただし、マップには、名前:Terry、年齢:26ではなく、名前: Terry、年齢:60というレコードが含まれています。

編集:提案をありがとうございました。私は非常に不注意な間違いを犯していたことがわかりました。キーに関連付けられた値を印刷する代わりに、キーのみを印刷していました。

誰もが指摘しているように、解決策は次のとおりです。

  for(Emp e: emp.keySet())
  {
        Emp empVal = emp.get(e);
        System.out.println("Name: " + empVal.name + " , age: " + empVal.age);
  }
4

3 に答える 3

2

出力は、値ではなくキーを出力しています。コードでは、キーは変更されませんが、値は変更されます。

たとえば、出力ループを次のように変更した場合:

for (Emp emp : emp.values()) {
  System.out.println("Name: " + e.name + " , age: " + e.age);
}

私はあなたがあなたが期待していた答えを見るだろうと思う。

ただし、一般的に、ここで行っていることを行わないようにアドバイスします。すべての種類のコードは、その場合、意味のある違いがまったくなく、クラスの実装がその契約に準拠していないことを想定a.equals(b)していますa。たとえば、ではなくを使用した場合、はるかに特殊な動作が発生し、それを修正する方法はありません。bEmpequalsHashSetHashMap

これを実装するためのより良い方法は、名前と年齢を適切に尊重するメソッドと、キーが従業員の名前で値がレコードであるマップを作成することEmpです。hashCodeequalsMap<String, Emp>Emp

于 2012-09-30T16:40:15.673 に答える
0

コードを少し修正しました-以下を参照してください。新しい値がマップに配置されますが、キーが等しいため、2番目の配置は既存のキーを再利用します。

public static void main(String[] args) {
    Emp e1 = new Emp("Terry", 26);
    Emp e2 = new Emp("Terry", 60);

    Map<Emp, Emp> emp = new HashMap<Emp, Emp>();
    emp.put(e2, e2);
    Emp v2 = emp.put(e1, e1);

    System.out.println("Replaced Record Name: " + v2.name + " , age: " + v2.age);
    for (Emp e : emp.keySet()) {
        System.out.println("[key] Name: " + e.name + " , age: " + e.age);
        System.out.println("[value] Name: " + emp.get(e).name + " , age: " + emp.get(e).age);
    }
}

出力:

[key] Name: Terry , age: 60
[value] Name: Terry , age: 26
于 2012-09-30T16:41:27.830 に答える
0

以下のステートメントでは、実際にキーを印刷しています。を呼び出すことにより、のキーkeySet()を取得し、それらのキーを繰り返し処理して印刷します。マップからこれらのキーの値をフェッチして印刷する必要があります。以下のステートメントを変更してください:-Setmap

System.out.println("Name: " + e.name + " , age: " + e.age);

と : -

System.out.println("Name: " + emp.get(e).name + " , age: " + emp.get(e).age);
于 2012-09-30T16:42:17.227 に答える