+ Start a Discussion
wsuycottwsuycott 

Multi dimension list/map notation help needed

Having alittle challenge in building multi dimensional lists and maps for a bulk processing class.  This is being designed to handle thousands of records, and given the limitations of 1000 members per list or per map I have chosen to handle by creating multiple lists and maps to address this.

 

Current code frag I am working on is indicating that I have a List Index out of Bounds:

 

List<List<OpportunityTeamMember>> otm = new List<List<OpportunityTeamMember>>();

List<Map<string,OpportunityTeamMember>> oppMap = new List<Map<string,OpportunityTeamMember>>();

 

j = 0; 

 

for(OpportunityTeamMember opt: [Select o.id, o.opportunityid, o.teammemberrole, o.opportunityaccesslevel, o.userid,

o.Opportunity.accountid From OpportunityTeamMember o where o.Opportunity.accountid in :accIds and isDeleted = False

and userid in :userIds])

  {

   j = setOffset(i);       //  sets the variable j up by 1 for each 1000 records read to move to next list array

   opplist[j].add(opt);  //  adds the record read to the list

 

   i++;                      //  increment the record count

 }

 

// Now, build maps from each list and construct a compound key

 for(j=0; j<10; j++)  {

    for(OpportunityTeamMember ox1: opplist[j])  {      oppMap[j].put(ox1.userid +

':' + ox1.Opportunity.accountid + ':' + ox1.opportunityid, ox1);

   }

In looking at the debug log it shows that the code fails on the first iteration through the for select loop after reading the record and that the setOffset(i) is returning a zero as expected.  The code doesn't make it to the map building phase, but I would assume that there will be a similar issue there as well.

 

I am assuming that I am not dereferencing the list properly, or that I am not creating it properly, or both.  Any assistance would be appreciated. 

Best Answer chosen by Admin (Salesforce Developers) 
Venkat PolisettVenkat Polisett

Does this work for you?

 

 

Integer i = 0;

List<Map<string,OpportunityTeamMember>> oppMap = new List<Map<string,OpportunityTeamMember>>(); 
Map<string,OpportunityTeamMember> innerMap;
 
for(OpportunityTeamMember otm: [select id, opportunityid, teammemberrole,
				       opportunityaccesslevel, userid, Opportunity.accountid 
				  from OpportunityTeamMember
				 where Opportunity.accountid in :accIds
				   and isDeleted = False
				   and userid in :userIds
				 ORDER BY  userid, Opportunity.accountid, opportunityid

LIMIT 10000] ) { if (math.mod(i, 1000) == 0) { innerMap = new Map<string,OpportunityTeamMember>(); oppMap.add(innerMap); } innerMap.put(otm.userid + ':' + otm.Opportunity.accountid + ':' + otm.opportunityid, otm); i++; }

All Answers

TSH53TSH53

Where is the declaration statement for opplist[]?

I see the declaration for otm - so is this a typo in the example below or a typo in the actual code?

 

For nested lists, make sure both the outer and inner lists are properly created as well as the entries within.

 

In the declaration for otm, an empty list is created. You need to create an inner list (via new) and then add it to the outer list in order to reference any element of it. If you don't, the reference of opplist[0] will give you the out of bounds error. Are you doing this in the setOffset method?

 

You should have code that looks something like this for each group of 1000 records (including the first group):

 

 

// Create an inner list and add it to the outer list. 

List<OpportunityTeamMember> innerList = new List<OpportunityTeamMember>();

otm.add(innerList);

 

Hope this helps and makes sense!

wsuycottwsuycott

Typo when I created the posting.  Here is the code:

 

List<List<OpportunityTeamMember>> opplist = new List<List<OpportunityTeamMember>>();

 

List<Map<string,OpportunityTeamMember>> oppMap = new List<Map<string,OpportunityTeamMember>>();

 

i=1;

for(OpportunityTeamMember opt: [Select o.id, o.opportunityid,o.teammemberrole,o.opportunityaccesslevel,o.userid,o.Opportunity.accountid

From OpportunityTeamMember o where o.Opportunity.accountid in :accIds and isDeleted = False and

userid in :userIds]) {

 

   j = setOffset(i);   // simply set j based on what 1000 records we are working on (0-1000 = 0, 1000-2000=1, etc)

 

  opplist[j].add(opt);

 

 i++;                     // increment number of records count

} // End of for loop over opportunityteam members

 // Now, build maps from each list 

for(j=0; j<10; j++) {

   for(OpportunityTeamMember ox1: opplist[j]) {       oppMap[j].put(ox1.userid + ':' + ox1.Opportunity.accountid + ':' + ox1.opportunityid, ox1);

   }

 }

 

Based upon your reply, would I need to explicity define each list of 1000 records as in the example below (and do I even need to nest a list definition within another to create the outerlist):

List<OpportunityTeamMember> innerlist1 = new List<OpportunityTeamMember>();

List<OpportunityTeamMember> innerlist2 = new List<OpportunityTeamMember>();

...

...

List<OpportunityTeamMember> innerlistn = new List<OpportunityTeamMember>();

 

List<List<OpportunityTeamMember>> outerlist = new List<List<OpportunityTeamMember>>();

 

outerlist.add(innerlist1);

outerlist.add(innerlist2);

 

Also, how would you dereference innerlist items from the outerlist (i.e.  OpportunityTeamMember oppMember = outerlist[0].innerlist[x])?  Or in the case of a list of maps - e.g. OpportunityTeamMember oppMapelement = outerlist[0].innerlist.get(keyname))?

 

Venkat PolisettVenkat Polisett

Does this work for you?

 

 

Integer i = 0;

List<Map<string,OpportunityTeamMember>> oppMap = new List<Map<string,OpportunityTeamMember>>(); 
Map<string,OpportunityTeamMember> innerMap;
 
for(OpportunityTeamMember otm: [select id, opportunityid, teammemberrole,
				       opportunityaccesslevel, userid, Opportunity.accountid 
				  from OpportunityTeamMember
				 where Opportunity.accountid in :accIds
				   and isDeleted = False
				   and userid in :userIds
				 ORDER BY  userid, Opportunity.accountid, opportunityid

LIMIT 10000] ) { if (math.mod(i, 1000) == 0) { innerMap = new Map<string,OpportunityTeamMember>(); oppMap.add(innerMap); } innerMap.put(otm.userid + ':' + otm.Opportunity.accountid + ':' + otm.opportunityid, otm); i++; }

This was selected as the best answer
wsuycottwsuycott

Thanks Venkat.  Your suggestion was right on target, and your offset solution of Math.Mod was far more elegant than the brute force coding I had done.  Regards,

 

 

Bill Suycott

VP Internal Systems/Director Enterprise Sales Operations

Metavante Technologies