繁体   English   中英

ConcurrentHashMap - 奇怪的行为

[英]ConcurrentHashMap - Odd behaviour

谁能让我知道这段代码出了什么问题? 我把头发拉出来!

如果我使用HashMap而不是ConcurrentHashMap没有任何问题。 代码使用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)

DummyKey.equals方法实现不正确,因为testMap.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();
}

这个问题是从equalsDummyKey

当你调用DummyValue val = testMap.get(key); 中, hashcode函数找到一个匹配(两个keynamek1key是相同的,所以他们的哈希码)。 然而,equals返回false,因为k1.keyname等于"A" ,它不等于key本身,实际上是DummyValue类型:你没有正确比较!

因此,您需要修改您的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;
}

请注意,如果更改hashCode(),则还必须更改equals()。 否则,你会遇到问题。 如果equals()为两个项返回true,那么它们的hashCode()值必须相等! 相反的不是必需的,但更好的散列性能。 这是equals()和hashCode()的实现。

提示:如果您使用的是eclipse,则可以利用其源代码生成功能为您创建正确的hashCode()和equals()方法。 您唯一需要做的就是选择标识对象的实例变量。 要在eclipse中执行此操作,请在源代码打开时,转到顶部的选项卡并选择“source”,然后选择“Generate hashCode()and 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);
  }

正如其他人指出的那样,问题在于你覆盖hashcode和equals的方式。 两个选项:1)只需删除哈希码和等号,它工作正常2)我让eclipse生成哈希码和等号的源,它工作正常。 这就是我的日食对我而言:

@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;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM