[SalesForce] Map/Set size when sobjects are duplicated

I have this below code where I create a map with sobject as key and integer as value.
I added 2 account sobject keys. Size is 2, and I later changed one of its names to the other one so that now they are duplicated.

Ideally map since it's a reference to sobject, changes should be reflected and map size should shrink to one. In my code, it does only if i do a system.debug of map before i calculate size/assert. It's the same behavior for set as well. Why is that so?

map<account,integer> mymap = new map<account,integer>();
account a = new account(name='apple');
mymap.put(a,1);
system.assertequals(mymap.size(),1);
mymap.put(new account(name='orange'),1);
system.assertequals(mymap.size(),2);
a.name='orange';
system.debug(mymap);//if i remove this my assertion will fail and size will be displayed as 2.if i add this statement before ,size is 1 and assertion succeeds
system.debug(mymap.size());
system.assertequals(mymap.size(),1);

Best Answer

I've come across a similar issue before in Using an sObject as a Map key.

From Map Considerations:

Uniqueness of map keys of user-defined types is determined by the equals and hashCode methods, which you provide in your classes. Uniqueness of keys of all other non-primitive types, such as sObject keys, is determined by comparing the objects’ field values.

And sObject Map Considerations

Be cautious when using sObjects as map keys. Key matching for sObjects is based on the comparison of all sObject field values. If one or more field values change after adding an sObject to the map, attempting to retrieve this sObject from the map returns null. This is because the modified sObject isn’t found in the map due to different field values. This can occur if you explicitly change a field on the sObject, or if the sObject fields are implicitly changed by the system; for example, after inserting an sObject, the sObject variable has the ID field autofilled. Attempting to fetch this Object from a map to which it was added before the insert operation won’t yield the map entry, as shown in this example.

Something interesting I found. As you say, the assertions pass when I run your sample code as anonymous apex with the Apex Code logging level set to DEBUG. However, with exactly the same code, if you set the Apex Code logging level to FINEST it will fail the assertion!