Question: Why doesn't my Java `HashMap` work? My object has the property that `.equals` equality implies `hashCode` equality.

You can assume that I'm modifying a field of the object after I add the object to the `HashMap`.

Answer: 
> 
> *You can assume that I'm modifying a field of the object after I add the object to the HashMap.*
> 
> 
> 

That right there is why.

[Javadoc says](https://docs.oracle.com/javase/8/docs/api/java/util/Map.html):

> 
> Note: great care must be exercised if mutable objects are used as map keys. **The behavior of a map is *not specified* if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map.**
> 
> 
> 

"Not specified" means "may not to work", so you should not be surprised when it doesn't work.
If you're mutating (changing) the objects *after* you add them to the `HashMap`, your objects will be in the wrong bucket. This is because even though the object has changed, the object is not "refiled" into the (new) correct bucket after the changes occur.

Thus, methods like `remove` will fail to find your object, because the object is sitting in an outdated bucket.

What really drives this home (for me) is that when the object is initially added to the `HashMap`, the hash value (an int) is stored with the Entry. This implies that the hash is a relatively static property that is rarely (never) updated.

Possible work-arounds include:

1. It'll probably work if you iterate through each Entry in the `hashmap` and create a new `HashMap` from those entries. This is probably bad in terms of performance but probably the most correct thing to do.
2. Don't include the field that's changing in your `hashCode` function. While not great (taking advantage of unspecified compiler behavior is risky business, at best), it tends to work, because you'll just have collisions, which only affect performance, not correctness. You still need to include the problematic field in your `.equals(Object obj)` method, or else you can end up removing the wrong objects.
3. Algorithmic solution: Find a way to store a different piece of data in the object that acts as the key that's constant. E.g., in my application, I was tracking the "age" of the object with an integer field. Every time I reached a certain amount of time in my application, I would go increment the age of all of the keys. If something was older than 50 units of time, then I could reasonably throw out the key-value pair. Alternatively, I could change the object to store the "birthtime" of the object. That is, if the application was 1000 time units old when the object was created, I'd store the number 1000. Then, to determine the age of the object, I could diff the current "time" against the birthtime and throw out the object if the difference was > 50.