function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Dave MedlicottDave Medlicott 

Question on a List of Lists of Strings

I must be doing something wrong, but I can't figure it out. Here's my code:

 

...

	List<List<String>> name1 = new List<List<String>>();
        List<String> name2 = new List<String>();
        name2.add('Fred');
        name2.add('Joe');
        System.debug(name2); //<--- Outputs DEBUG|(Fred, Joe)
        
	name1.add(name2);
        System.debug(name1); //<--- Outputs DEBUG|((Fred, Joe))
        
	name2.clear();
        name2.add('Mary');
        name2.add('Jane');
        System.debug(name2); //<--- Outputs DEBUG|(Mary, Jane)
        
	name1.add(name2);
        System.debug(name1); //<--- DEBUG|((Mary, Jane), (already output))

 


I would have expected that last one to output ((Fred, Joe), (Mary, Jane))
Any idea of what's going on?

 

Thanks, Dave

Best Answer chosen by Admin (Salesforce Developers) 
Puja_mfsiPuja_mfsi

Hi,

When u declare a string and instantiate it ,create a pointer reference in memory ,then when you clear the first list it means the 'line1' reference to null list and the 'allLines' list become empty and next time it contains the Null.

In second time if you add anew value in 'line1' it contains the new value and add it to the  'allLines' .so in both the time the new value is added to the 'allLines' list.

 

There is a solution to overcome this problem:

 

For (integer count = 0; count < max; count++){
       if (test case 1){
              line1.add('a');
       } else if (test case 2){
              line1.add('b');
      } else {

              List<String> tempList = new List<String>( line1);
              allLines.add(tempList);
              line1.clear();
      }
}

 

u need to create a new string and store the 'line' value in the new list and add it to the 'allLines' list.

 

 

Please let me know if u have any issue on same and if this post helps u please give KUDOS by click on star at left.

 

All Answers

crop1645crop1645

'already output' is a SFDC debug log 'feature' wherein it won't redisplay lists of things it has already displayed in order to save space in the log

 

Your name1 variable does in fact have two elements as you expect

Dave MedlicottDave Medlicott

Thanks, but that's not correct. It saves room by doing something like ... It outputs 'already output' when it's the same. Just to be certain,  I changed the System.Debug statement to System.debug(name1[0] + ' ' + name1[1]); and the output is (Mary, Jane) (Mary, Jane). 

 

 

crop1645crop1645
Sheesh, you are right ...I'll need to think about this more. It is not a winter 14 sandbox issue as same results in PROD
crop1645crop1645

I know why, here you go

 

	List<List<String>> name1 = new List<List<String>>();
        List<String> name2 = new List<String>();
        name2.add('Fred');
        name2.add('Joe');
        System.debug(name2); //<--- Outputs DEBUG|(Fred, Joe)
        
	name1.add(name2);
        System.debug(name1); //<--- Outputs DEBUG|((Fred, Joe))
        
	name2.clear();
        // at this point name1 has 1 element, that element is referred to by variable name2 with value ()
        name2.add('Mary');
        name2.add('Jane');
        System.debug(name2); //<--- Outputs DEBUG|(Mary, Jane)
        
	name1.add(name2);
        // Here you are adding the second element to name1, but using the same variable name2 so each element of name1 refers to the same place in memory, that is name2. Hence the output is ((mary jane), (mary jane))
        System.debug(name1); //<--- DEBUG|((Mary, Jane), (already output))

 

Dave MedlicottDave Medlicott

Really? I can't understand how that could be useful in any way. And worse ... I can't think of a way to overcome this in my 'real' code. My 'real' code looks something like this:

List<List<String>> allLines = new List<List<String>>();
List<String> line1 = new List<String>();

... 

For (integer count = 0; count < max; count++){
	if (test case 1){
		line1.add('a');
	} else if (test case 2){
		line1.add('b');
	} else {
		allLines.add(line1);
		line1.clear();
	}
}

 If I moved the List<String> line1 = new List<String>(); inside the For loop, it would work ... except that I'd lose the values accumlated in 'Line1' from prior iterations (e.g.if I did that and if test case 1 was true twice in a row, I'd only end up with only 'a' in my List instead of 'aa').

 

If you have any ideas, I'd be interested in hearing them.

Puja_mfsiPuja_mfsi

Hi,

When u declare a string and instantiate it ,create a pointer reference in memory ,then when you clear the first list it means the 'line1' reference to null list and the 'allLines' list become empty and next time it contains the Null.

In second time if you add anew value in 'line1' it contains the new value and add it to the  'allLines' .so in both the time the new value is added to the 'allLines' list.

 

There is a solution to overcome this problem:

 

For (integer count = 0; count < max; count++){
       if (test case 1){
              line1.add('a');
       } else if (test case 2){
              line1.add('b');
      } else {

              List<String> tempList = new List<String>( line1);
              allLines.add(tempList);
              line1.clear();
      }
}

 

u need to create a new string and store the 'line' value in the new list and add it to the 'allLines' list.

 

 

Please let me know if u have any issue on same and if this post helps u please give KUDOS by click on star at left.

 

This was selected as the best answer
Dave MedlicottDave Medlicott

Thanks to both Eric & Puja! Adding that 'tempList' did the trick.