[SalesForce] How to iterate through map entries for a single key value? Maps with a value of type list

I have a map which has more then one entry for each key value, how can I iterate through just those records for a particular key value. I don't want to do the following which iterates through the whole set, but just want to iterate through those for a particular key value, struggling to find the right syntax – probably missing something straightforward!

Map<id,List<ERP_Customer__c>> acctErpMap = new Map<id,List<ERP_Customer__c>>();

// code to put values in map to go here ... 

for (id key : acctErpMap.keyset())  
{  
    System.debug(logginglevel.INFO, 'PersonAccount DEBUG: MAP key = ' + key);  
    System.debug(logginglevel.INFO, 'PersonAccount DEBUG: MAP value = ' + acctErpMap.get(key));         
}

Following the help given by those who responded to the call I re-coded as per following:
1. A map of lists has been created.
2. The id of the map has therefore been able to be kept unique
3. The code now posted below shows:
(a) Setting up and populating the map.
(b) Reading back through the map.

/*****************************************************************
    Note: ERP_Customer__c is a child of the Account object.
    Create a map, acctErpMap, of lists as follows:
******************************************************************/ 
Map<id,List<ERP_Customer__c>> acctErpMap = new Map<id,List<ERP_Customer__c>>();
// Create an empty ERP list for each account record. 
For (Account acc : accList) 
{ 
    acctErpMap.put(acc.id, new List<ERP_Customer__c>());
}

//    Populate ERP_Customer__c list for each account being processed                 
for (ERP_Customer__c ERPChild : ERPFullList)
{
    acctErpMap.get(ERPChild.PersonAccount__c).add(ERPChild);
}

// Loop through accounts.
For (Account acc : accList)
{ 
    // Logic removed for purpose of post.
    // ...

    // Loop through ERP_Customer__c for this Account
    for (ERP_Customer__c ERPChild : acctErpMap.get(acc.id))
    {      
        // Logic removed for purpose of post...
        // ...
    }               
}

Best Answer

You can only have one value per key in a map. Calling Map.put(...) on the same key will replace the existing value in the given key.

Try running the snippet below in a developer console to display this behavior.

Map<String, Boolean> mapAndValues = new Map<String, Boolean>();

// Assign multiple values to same key 
mapAndValues.put('test', true);
mapAndValues.put('test', false);

System.debug(mapAndValues.get('test')); // will return false

An alternative option to using put on the same key would be to use a list type as the value to the map.

Map<String, List<Boolean>> mapAndValues = new Map<String, List<Boolean>>();

// Assign empty list  
mapAndValues.put('test', new List<Boolean>());

// Modify list reference from get 
mapAndValues.get('test').add(true);
mapAndValues.get('test').add(false);

System.debug(mapAndValues.get('test')); // will return (true, false) 

To iterate over the records in your list as specified in your question, you'll need to create a loop which acts on the list provided from calling get on the key.

// First log id to be used to get other records 
System.debug(logginglevel.INFO, 'PersonAccount DEBUG: MAP key = ' + id);  

// Loop over list at specified key 
for (ERP_Customer__c erp:acctErpMap.get(id))  
{  
    // Log each record 
    System.debug(logginglevel.INFO, 'PersonAccount DEBUG: MAP value = ' + erp.Id);         
}

To check if a key is in a map, you need to use the method containsKey(...), as opposed to the method contains.

someMap.containsKey(someKey); // returns either true or false