+ Start a Discussion
DbjensenDbjensen 

Help: for loop only adding one key value to map

Hello - I have a list that that finds the the opportunity line items related to an opporunity. I'm adding the opportunity line item ids to a map using a for loop. However, only 1 key value is getting added to the map - even when the list contains multiple values. Could you let me know why the for loop is only adding 1 key value to the map?

//list of opportunity line items related to the opportunity
List<OpportunityLineItem> oliList = [SELECT Id, OpportunityId, Product_Name__c FROM 
                                             OpportunityLineItem WHERE OpportunityId IN :mapNewOpp.keySet()];
    
    system.debug('Opp Line Items in List ' +oliList);
        
        map<Id, String> mapOfOLI = new Map<Id, String>();
        
        for(OpportunityLineItem oliFromList : oliList) {
            mapOfOLI.put(oliFromList.OpportunityId, oliFromList.Product_Name__c);
        }
        
        system.debug('opp product names in map ' +mapOfOLI);
Best Answer chosen by Dbjensen
Narender Singh(Nads)Narender Singh(Nads)
Hi,
Now I see why you are not getting two values in your map.
If you look carefully, your query is returning two results with same OpportunityLineItem ID and  same Opportunity ID.
OpportunityLineItem:{Id=00k1D000002cG6UQAU, OpportunityId=0061D000001elIOQAY, Product_Name__c=Data license;}
OpportunityLineItem:{Id=00k1D000002cG6VQAU, OpportunityId=0061D000001elIOQAY, Product_Name__c=Focus_Explorer_API;}

And the thing with map is that all the keys in the map are unique. So after first iteration, your map is:
{0061D000001elIOQAY=Data license;}
but the after second iteration, in your map the value gets updated rather than being inserted as a new key value pair because the opportunity id already exists in the map. So your map looks like:
{0061D000001elIOQAY=Focus_Explorer_API;}

In order to overcome this, use a map of structure as shown:
map<id,list<string>> mp=new map<id,list<string>>();
for(OpportunityLineItem oliFromList : oliList){
    if(mp.containsKey(oliFromList.OpportunityId)){
        string[] ls=mp.get(oliFromList.OpportunityId);
        ls.add(oliFromList.Product_Name__c);
        mp.put(oliFromList.OpportunityId,ls);
    }
    else{
        string[] ls=new string[]{};
        ls.add(oliFromList.Product_Name__c);
        mp.put(oliFromList.OpportunityId,ls);
    }
}



Let me know if it helps.
Thanks!

All Answers

Hemant_SoniHemant_Soni
Hi,
Please try below code. I guess by mistake you are adding opportunity id in map so i have updated code so use that.
//list of opportunity line items related to the opportunity
List<OpportunityLineItem> oliList = [SELECT Id, OpportunityId, Product_Name__c FROM 
                                             OpportunityLineItem WHERE OpportunityId IN :mapNewOpp.keySet()];
    
    system.debug('Opp Line Items in List ' +oliList);
        
        map<Id, String> mapOfOLI = new Map<Id, String>();
        
        for(OpportunityLineItem oliFromList : oliList) {
            mapOfOLI.put(oliFromList.Id, oliFromList.Product_Name__c);// This is the line where i have changed.
        }
        
        system.debug('opp product names in map ' +mapOfOLI);
Thanks
Hemant
 
Narender Singh(Nads)Narender Singh(Nads)
Hi, 
Your code looks fine. I think the reason for just one key value in your map is because your SOQL query is returning only a single result.

Can you tell me what are you getting in the debugged logs for 'oliList'.
Put a system.debug to check the size of the list, like this:
system.debug('oliList size:  ' +oliList.size());

Let me know what results you are getting.
DbjensenDbjensen
Hi Narender - Here's the debug resutls. I added a debug size. (I bolded the results I'm trying to pull into the map.)

system.debug('Opp Line Items in List ' +oliList);
  • |DEBUG|opp line items found (OpportunityLineItem:{Id=00k1D000002cG6UQAU, OpportunityId=0061D000001elIOQAY, Product_Name__c=Data license;}, OpportunityLineItem:{Id=00k1D000002cG6VQAU, OpportunityId=0061D000001elIOQAY, Product_Name__c=Focus_Explorer_API;})
system.debug('oliList size:  ' +oliList.size());
  • USER_DEBUG [33]|DEBUG|oliList size: 2
system.debug('opp product names in map ' +mapOfOLI);
  • DEBUG|values in opp line item map{0061D000001elIOQAY=Focus_Explorer_API;}
DbjensenDbjensen
Hi Hemant - I need to pull in the opp Id because I use that Id in the following code. 

for(Opportunity opp : newOpp) {
            if(mapOfOldOpps.values() != mapOfnewOpps.values() && !oppLinImList.isEmpty()) {
                opp.Products_2__c = mapOLI.get(opp.Id);
                oppList.add(opp);
            } else if (oppLinImList.isEmpty()){
                opp.Products_2__c = null;
                oppList.add(opp);
            }
        }
        
        try{
            update oppList;
        } catch (Exception e) {
            system.debug('Opp product field did not update ' +e);
        } 
Narender Singh(Nads)Narender Singh(Nads)
Hi,
Now I see why you are not getting two values in your map.
If you look carefully, your query is returning two results with same OpportunityLineItem ID and  same Opportunity ID.
OpportunityLineItem:{Id=00k1D000002cG6UQAU, OpportunityId=0061D000001elIOQAY, Product_Name__c=Data license;}
OpportunityLineItem:{Id=00k1D000002cG6VQAU, OpportunityId=0061D000001elIOQAY, Product_Name__c=Focus_Explorer_API;}

And the thing with map is that all the keys in the map are unique. So after first iteration, your map is:
{0061D000001elIOQAY=Data license;}
but the after second iteration, in your map the value gets updated rather than being inserted as a new key value pair because the opportunity id already exists in the map. So your map looks like:
{0061D000001elIOQAY=Focus_Explorer_API;}

In order to overcome this, use a map of structure as shown:
map<id,list<string>> mp=new map<id,list<string>>();
for(OpportunityLineItem oliFromList : oliList){
    if(mp.containsKey(oliFromList.OpportunityId)){
        string[] ls=mp.get(oliFromList.OpportunityId);
        ls.add(oliFromList.Product_Name__c);
        mp.put(oliFromList.OpportunityId,ls);
    }
    else{
        string[] ls=new string[]{};
        ls.add(oliFromList.Product_Name__c);
        mp.put(oliFromList.OpportunityId,ls);
    }
}



Let me know if it helps.
Thanks!
This was selected as the best answer
DbjensenDbjensen
Oh, got it. Thanks so much. This is very helpful. I have one more question for you, if you don't mind. Now that I have these product names in the map, I need to add them to a text field caled Products_2__c. Below is the code I had originally, but now that the map contains a list, how do I get the names from the map and populate the Products_2__c field? 

for(Opportunity opp : newOpp) {
            if(mapOfOldOpps.values() != mapOfnewOpps.values() && !oppLinImList.isEmpty()) {
                opp.Products_2__c = mapOfOLI .get(opp.Id);
                oppList.add(opp);
            }
Narender Singh(Nads)Narender Singh(Nads)
Hi,

Your code will look like this:
 
for(Opportunity opp : newOpp) {
    if(mapOfOldOpps.values() != mapOfnewOpps.values() && !oppLinImList.isEmpty()) {
        string[] ProductList= mapOfOLI .get(opp.Id);
        if(ProductList.size()>0){
            for(string s:ProductList){
                if(opp.Products_2__c==NULL){
                    opp.Products_2__c=s; 
                }
                else{
                    opp.Products_2__c=opp.Products_2__c+' \n'+s;
                }
             }
    	}
    	oppList.add(opp);
	}
}

Let me know if it helps.
Thanks 
 
DbjensenDbjensen
This is fantastic. It works great. Thanks very much. You are awesome. I really appreciate your help.