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); System.debug(a); }
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 –
- 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));