2

このコードの何が問題なのか誰か教えてもらえますか? 髪を引っ張ってる!

ConcurrentHashMap の代わりに HashMap を使用しても問題ありません。コードはJDK 5.0でコンパイルされています

public class MapTest {
    public Map<DummyKey, DummyValue> testMap = new ConcurrentHashMap<DummyKey, DummyValue>();

  public MapTest() {
      DummyKey k1 = new DummyKey("A");
      DummyValue v1 = new DummyValue("1");
      DummyKey k2 = new DummyKey("B");
      DummyValue v2 = new DummyValue("2");

      testMap.put(k1, v1);
      testMap.put(k2, v2);
  }

  public void printMap() {
      for(DummyKey key : testMap.keySet()){
          System.out.println(key.getKeyName());
          DummyValue val = testMap.get(key);
          System.out.println(val.getValue());
      }
  }

  public static void main(String[] args){
      MapTest main = new MapTest();
      main.printMap();
  }


  private static class DummyKey {
      private String keyName = "";

      public DummyKey(String keyName){
        this.keyName = keyName;
      }

      public String getKeyName() {
        return keyName;
      }

      @Override
      public int hashCode() {
        return keyName.hashCode();
      }

  @Override
      public boolean equals(Object o) {
         return keyName.equals(o);
      }
  }

  private static class DummyValue {
      private String value = "";

      public DummyValue(String value){
         this.value = value;
      }

      public String getValue() {
        return value;
      }
   }
}

これは出力です:

B
Exception in thread "main" java.lang.NullPointerException
at test.MapTest.printMap(MapTest.java:27)
at test.MapTest.main(MapTest.java:34)
4

4 に答える 4

7

DummyKey.equalstestMap.get(key)常に null を返すため、メソッドの実装は正しくありません。これを試して

public boolean equals(Object o) {
    if (o instanceof DummyKey) {
        DummyKey other = (DummyKey) o;
        return keyName == null ? other.keyName == null : keyName.equals(other.keyName);
    }
    return false;
}

hashCode も equals との一貫性を保つために少し変更する必要があります

public int hashCode() {
    return keyName == null ? 0 : keyName.hashCode();
}
于 2013-07-10T08:25:18.697 に答える
1

他の人が指摘したように、問題は hashcode と equals をオーバーライドする方法にあります。2 つのオプション: 1) ハッシュコードと equals を削除するだけで正常に動作します 2) eclipse にハッシュコードと equals のソースを生成させ、正常に動作させます。これは私の日食が私のためにベルトアウトしたものです:

@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((keyName == null) ? 0 : keyName.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        DummyKey other = (DummyKey) obj;
        if (keyName == null) {
            if (other.keyName != null)
                return false;
        } else if (!keyName.equals(other.keyName))
            return false;
        return true;
    }
于 2013-07-10T14:47:03.557 に答える
1

問題はあなたのequals中にありDummyKeyます。

を呼び出すDummyValue val = testMap.get(key);と、hashcode関数は一致を見つけます (との両方keynameが同じで、ハッシュコードも同じです)。しかし、equals は false を返します。is equal toはそれ自体と等しくなく、実際には typeです: 適切に比較していません!k1keyk1.keyname"A"keyDummyValue

したがって、equals 関数を次のように変更する必要があります。

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    DummyKey other = (DummyKey) obj;
    if (keyName == null) {
        if (other.keyName != null)
            return false;
    } else if (!keyName.equals(other.keyName))
        return false;
    return true;
}
于 2013-07-10T08:29:28.310 に答える
1

hashCode() を変更する場合は、equals() も変更する必要があることに注意してください。そうしないと、問題が発生します。equals() が 2 つのアイテムに対して true を返す場合、それらの hashCode() 値は等しい必要があります。逆は必須ではありませんが、ハッシュのパフォーマンスを向上させるために推奨されます。これは equals() と hashCode() の実装です。

ヒント: Eclipse を使用している場合は、そのソース生成機能を利用して、正しい hashCode() および equals() メソッドを作成できます。オブジェクトを識別するインスタンス変数を選択するだけです。Eclipse でこれを行うには、ソース コードが開いている間に、上部のタブに移動し、[ソース] を選択してから、[hashCode() と equals() を生成する...] を選択します。

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((keyName == null) ? 0 : keyName.hashCode());

    return result;
  }

  Override
  public boolean equals(Object other) {
     if(this == other) return true; //for optimization
     if(! other instanceof this) return false; //also covers for when other == null
     return this.keyName == null ? other.keyName == null : this.keyName.equals(other.keyName);
  }
于 2013-07-10T08:47:10.250 に答える