I was very excited to learn about the new getPopulatedFieldsAsMap() method added to the SObject class with Summer '16. Unfortunately upon testing I found what appears to be a bug based on my understanding. The method is intended to allow developers to easily obtain fields populated in memory. According to the docs:
A field is populated in memory in the following cases.
The field has been queried by a SOQL statement.
The field has been explicitly set before the call to the getPopulatedFieldsAsMap() method.
In practice, I've found that if a field is not included in a SOQL query when retrieving an existing record it will be excluded from the field map returned by the new method, even if it was explicitly set before the call:
Contact c = [SELECT Name FROM Contact LIMIT 1];
c.Title = 'President';
Map<String,Object> fieldsMap = c.getPopulatedFieldsAsMap();
System.debug(fieldsMap);
// DEBUG|{Id=003XXXXXXXXXXXXXXX, Name=Jack Rogers}
// Note: Title field is not returned
However, a field explicitly set before the call is included in the case of a new SObject instance:
Contact c = new Contact();
c.Title = 'President';
Map<String,Object> fieldsMap = c.getPopulatedFieldsAsMap();
System.debug(fieldsMap);
// DEBUG|{Title=President}
Here is a gist that can be run in the dev console to see first hand what I'm experiencing. AFAICT this seems like a bug, but I'm curious to hear if others see it as expected behavior.
@AndyFawcett has kindly opened a case with Salesforce developer support-I will update this post with their response once we know more.