Strange Java HashMap Behavior - Cannot Find Matching Object

I came across some strange behavior when trying to find the key inside java.util.HashMap, and I think I missed something. The code segment is basically:

HashMap<Key, Value> data = ...
Key k1 = ...

Value v = data.get(k1);
boolean bool1 = data.containsKey(k1);
for (Key k2 : data.keySet()) {
    boolean bool2 = k1.equals(k2);
    boolean bool3 = k2.equals(k1);
    boolean bool4 = k1.hashCode() == k2.hashCode();
    break;
}

It is strange to cycle because of specific performance , I know that datacontains only one element at this point, and it is k1, indeed bool2, bool3and bool4will be evaluated before truethe execution. bool1, however, will be evaluated as false, and vwill be null.

- , , , , .

EDIT: , - , , , . , ?

+3
6

, - , .

:

public class Key
{
int hashCode = 0;

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

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Key other = (Key) obj;
    return hashCode == other.hashCode;
}

public static void main(String[] args) throws Exception {
    HashMap<Key, Integer> data = new HashMap<Key, Integer>();
    Key k1 = new Key();
    data.put(k1, 1);

    k1.hashCode = 1;

    boolean bool1 = data.containsKey(k1);
    for (Key k2 : data.keySet()) {
        boolean bool2 = k1.equals(k2);
        boolean bool3 = k2.equals(k1);
        boolean bool4 = k1.hashCode() == k2.hashCode();

        System.out.println("bool1: " + bool1);
        System.out.println("bool2: " + bool2);
        System.out.println("bool3: " + bool3);
        System.out.println("bool4: " + bool4);

        break;
    }
}
}
+9

API :

: , . , , . , , . , , : equals hashCode .

, equals() hashCode() , . undefined.

+3

, - , , , , - . , java.util.HashMap, - ? , JVM ?

java.util.HashMap.getEntry(Object key) Sun 1.6.0_20 JVM:

final Entry<K,V> getEntry(Object key) {
    int hash = (key == null) ? 0 : hash(key.hashCode());
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
         e != null;
         e = e.next) {
        Object k;
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
            return e;
    }
    return null;

, hashCode, , equals . , , - , , .

- hashCode equals Key .

, . , , containsKey, , .

+1

Is this app multithreaded? If so, another thread may change the data between the call data.containsKey(k1)and the call data.keySet().

0
source

If equals () returns true for two objects, hashCode () should return the same value. If equals () returns false, then hashCode () must return different values. For reference:

http://www.ibm.com/developerworks/java/library/j-jtp05273.html

0
source

Perhaps the Key class looks like

Key
{
    boolean equals = false ;

    public boolean equals ( Object oth )
    {
         try
         {
              return ( equals ) ;
         }
         finally
         {
              equals = true ;
         }
    }
}
0
source

Source: https://habr.com/ru/post/1757029/


All Articles