Java - map.get不起作用,但元素在map中?

时间:2014-05-01 14:06:53

标签: java hashmap equals

所以......一切都在代码中:

// get vector...
SignVector v = ...;

//print to console: [1058, 5, 820 in flat]
System.out.println(v);

//size: 1
System.out.println("size: " + signs.size());

//check all elements...
for (Entry<SignVector, FakeSign> entry : signs.entrySet())
{
    // get key
    SignVector key = entry.getKey();

    //print to console: [1058, 5, 820 in flat] (YaY! it's that key! like v)
    System.out.println(key);
    if (key.equals(v))
    {
        // print: "YaY: " 
        System.out.println("YaY: [1058, 5, 820 in flat]"+key);
    }
}
//So second test... just get it from map: null
System.out.println(signs.get(v));

为什么返回null?
在JavaDocs中写道:map.get使用key.equals(k)为什么我的代码返回好的对象,但map.get返回null?

地图: private final Map<SignVector, FakeSign> signs = new HashMap<>()



@home用户的等号方法形式为SignVector

@Override
public boolean equals(Object obj)
{
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    SignVector other = (SignVector) obj;
    // w can't be null so I skip that
    System.out.print(w.getName() + ", " + other.w.getName() + ", " + (w.getName().equals(other.w.getName()))); // this same
    if (!w.getName().equals(other.w.getName()))
        return false;
    if (x != other.x)
        return false;
    if (y != other.y)
        return false;
    if (z != other.z)
        return false;
    return true;
}

但是这种方法效果很好,总是返回我想要的,xyzintw是自定义对象。< / p>

2 个答案:

答案 0 :(得分:4)

javadoc有点误导,但它依赖的事实是,如果你实现equals,你还应该实现hashcode以保持一致。正如文件所述:

  

集合框架接口中的许多方法都是用术语定义的   等于方法。例如,规范   containsKey(Object key)方法说:“当且仅当这个时返回true   map包含键k的映射,使得(key == null?k == null:   key.equals(k))。“

     

本说明书不应解释为暗示   使用非null参数键调用Map.containsKey将导致   key.equals(k)将被调用任何密钥k。

     

实施是免费的   实现优化,从而避免等于调用   例如,首先比较两个密钥的哈希码。 (该   Object.hashCode()规范保证两个对象具有   不等的哈希码不能相等。)

     

更一般地说,实现   可以免费使用各种Collections Framework接口   底层Object方法的指定行为的优点   实施者认为合适的地方。

让我们看一下get HashMap的基础实现。

314  public V get(Object key) {
315      if (key == null)
316          return getForNullKey();
317      int hash = hash(key.hashCode());
318      for (Entry<K,V> e = table[indexFor(hash, table.length)];
319           e != null;
320           e = e.next) {
321          Object k;
322          if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
323              return e.value;
324      }
325      return null;
326  }

您看到它使用对象的哈希码来查找表中的可能条目,然后它使用equals来确定它必须返回的值。由于条目可能为null,因此跳过for循环,get返回null

覆盖hashCode课程中的SignVector以与equals保持一致,一切正常。

答案 1 :(得分:1)

来自javadocs:

  

如果此映射允许空值,则返回值null不一定表示映射不包含该键的映射;它也可能是地图显式地将键映射为null。 containsKey操作可用于区分这两种情况。

除非您与我们分享您如何构建地图,否则我们无法帮助您(如果是这种情况)。您共享的代码应该正常工作。

http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#get%28java.lang.Object%29