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.
Another scenario
where sObject fields are autofilled is in triggers, for example, when
using before and after insert triggers for an sObject. If those triggers
share a static map defined in a class, and the sObjects in Trigger.New are added to this map
in the before trigger, the sObjects in Trigger.New in the after trigger aren’t found in
the map because the two sets of sObjects differ by the fields that
are autofilled. The sObjects in Trigger.New in the after trigger have system fields populated after insertion,
namely: ID, CreatedDate, CreatedById, LastModifiedDate, LastModifiedById,
and SystemModStamp.
// Create an account and add it to the map
Account a1 = new Account(Name='A1');
Map<sObject, Integer> m = new Map<sObject, Integer>{
a1 => 1};
// Get a1's value from the map.
// Returns the value of 1.
System.assertEquals(1, m.get(a1));
// Id field is null.
System.assertEquals(null, a1.Id);
// Insert a1.
// This causes the ID field on a1 to be auto-filled
insert a1;
// Id field is now populated.
System.assertNotEquals(null, a1.Id);
// Get a1's value from the map again.
// Returns null because Map.get(sObject) doesn't find
// the entry based on the sObject with an auto-filled ID.
// This is because when a1 was originally added to the map
// before the insert operation, the ID of a1 was null.
System.assertEquals(null, m.get(a1));