Maps Collection and Map of sObject

A map is a collection of key-value pairs where each unique key maps to a single value. Keys and values can be any data type—primitive types, collections, sObjects, user-defined types, and built-in Apex types.

Map keys and values can contain any collection, and can contain nested collections. For example, you can have a map of Integers to maps, which, in turn, map Strings to lists.

You can use the generic or specific sObject data types with maps.

Map Considerations –
  • Apex developers do not need to reference the algorithm that is used to implement a map in their declarations (for example, HashMap or TreeMap). Apex uses a hash structure for all maps.
  • The iteration order of map elements is deterministic.
  • A map key can hold the null value.
  • Adding a map entry with a key that matches an existing key in the map overwrites the existing entry with that key with the new entry.
  • Map keys of type String are case-sensitive.
  • Uniqueness of map keys of user-defined types is determined by the equals and hashCode methods.
  • A Map object is serializable into JSON only if it uses one of the following data types as a key.
Maps of sObject – 

Map keys and values can be of any data type, including sObject types, such as Account.

Maps can hold sObjects both in their keys and values. A map key represents a unique value that maps to a map value.

Q- Can we declare a map like below.[Interview Question]

Map<sObject, List> mapTest = new Map<sObject, List>();

Ans – Yes, you can declare with out any issue.

Maps allow sObjects in their keys. You should use sObjects in the keys only when the sObject field values won’t change.

Populating Map from SOQL query –

Maps can be directly populated from the results returned by the SOQL query. The map key should be declared with an ID or String data type, and the map value should be declared as an sObject data type.

// Populate map from SOQL query
Map<ID, Account> accMap = new Map<ID, Account>([SELECT Id, Name FROM Account LIMIT 10]);
// After populating the map, iterate through the map entries
for (ID idKey : accMap.keyset()) {
Account a = accMap.get(idKey);

Few Map Methods –

Account myAcct = new Account(); //Define a new account
Map<Integer, Account> m = new Map<Integer, Account>(); // Define a new map
m.put(1, myAcct); // Insert a new key-value pair in the map
System.assert(!m.containsKey(3)); // Assert that the map contains a key
Account a = m.get(1); // Retrieve a value, given a particular key
Set<Integer> s = m.keySet(); // Return a set that contains all of the keys in the map

sObject Map Considerations –
  1. Using sObject as map key.

Be careful when using sObject 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.

2.  Using sObject map key field in Trigger

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.debug('Map value='+m.get(a1));
// Id field is null, as the Account is not inserted
System.debug('Map value 2='+a1.Id);

// Insert a1.This causes the ID field on a1 to be auto-filled
insert a1;
// Id field is now populated.
System.debug('Acc value='+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.debug('Map value again='+m.get(a1));

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s