Question

So... all is in code:

// 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));

Why that return null?
In JavaDocs is written that: map.get using key.equals(k) so why my code return good object, but map.get return null?

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



Equals method form SignVector for @home user

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

But this method works good, always return that I want, x,y,z is int, and w is custom object.

Était-ce utile?

La solution

The javadoc is a bit misleading, but it's relying on the fact that if you implement equals, you should also implement hashcode to be consistent. As the doc states:

Many methods in Collections Framework interfaces are defined in terms of the equals method. For example, the specification for the containsKey(Object key) method says: "returns true if and only if this map contains a mapping for a key k such that (key==null ? k==null : key.equals(k))."

This specification should not be construed to imply that invoking Map.containsKey with a non-null argument key will cause key.equals(k) to be invoked for any key k.

Implementations are free to implement optimizations whereby the equals invocation is avoided, for example, by first comparing the hash codes of the two keys. (The Object.hashCode() specification guarantees that two objects with unequal hash codes cannot be equal.)

More generally, implementations of the various Collections Framework interfaces are free to take advantage of the specified behavior of underlying Object methods wherever the implementor deems it appropriate.

Let's take a look a the underlying implementation of get for an 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  }

You see that is uses the hashcode of the object to find the possible entries in the table and THEN it uses equals to determine which value it has to return. Since the entry is probably null, the for loop is skipped and get returns null.

Override hashCode in your SignVector class to be consistent with equals and everything should work fine.

Autres conseils

From the javadocs:

If this map permits null values, then a return value of null does not necessarily indicate that the map contains no mapping for the key; it's also possible that the map explicitly maps the key to null. The containsKey operation may be used to distinguish these two cases.

Unless you share with us how you built the map, we can't help you if this is the case. The code you shared should otherwise be working just fine.

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top