Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ConcurrentHashMap - Odd behaviour

Can anyone let me know what goes wrong in this piece of code? I'm pulling my hair out!

There isn't any problem if I use HashMap instead of ConcurrentHashMap. The code is compiled with 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;
      }
   }
}

This is the output:

B
Exception in thread "main" java.lang.NullPointerException
at test.MapTest.printMap(MapTest.java:27)
at test.MapTest.main(MapTest.java:34)
like image 471
TommyQ Avatar asked Jun 04 '26 23:06

TommyQ


2 Answers

DummyKey.equals method implementation is incorrect, due to that testMap.get(key) always returns null. Try this

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 also needs a little change to be consistent with equals

public int hashCode() {
    return keyName == null ? 0 : keyName.hashCode();
}
like image 55
Evgeniy Dorofeev Avatar answered Jun 06 '26 12:06

Evgeniy Dorofeev


The problem comes from your equals in DummyKey.

When you call DummyValue val = testMap.get(key);, the hashcode function finds a match (both keyname of k1 and key are the same and so are their hashcode). Yet equals returns false because k1.keyname is equal to "A" which is not equal to key itself, which is actually of type DummyValue: you are not comparing properly!

Therefore, you need to modify your equals function:

@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;
}
like image 42
Jean Logeart Avatar answered Jun 06 '26 12:06

Jean Logeart



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!