0

I am fairly new to Java and am trying to load a LinkedHashMap that contains an ArrayList of values. I am trying to load the values from a query result from an API based query result (Salesforce).

Here is the error: "Cannot refer to a non-final variable breakdown inside an inner class defined in a different method" - the breakdown variable is underlined in red giving this message, Ive noted the line in concern below.

CODE

public LinkedHashMap<String, ArrayList<String>> sfFundIdsByContact; public ArrayList<String> getFundsIDsForContact(Contact aContact) { QueryResult queryResults = null; ArrayList<String> ids = new ArrayList<String>(); int index = 0; Boolean done = false; String contactid = aContact.getId(); String SCCPBId = null; if(sfFundIdsByContact == null || sfFundIdsByContact.size() <= 0){ //Do the Salesforce API CALL and Return the results ... while (! done) { SObject[] records = queryResults.getRecords(); for ( int i = 0; i < records.length; ++i ) { if(sfFundIdsByContact.containsKey(breakdown.getSalesConnect__Contact__c())){ sfFundIdsByContact.get(breakdown.getSalesConnect__Contact__c()).add(breakdown.getId()); } else { //Line below in the add(breakdown.getId() - contains the error sfFundIdsByContact.put(breakdown.getSalesConnect__Contact__c(), new ArrayList<String>() {{ add(breakdown.getId()); }}); } } 

All suggestions are appreciated.

3
  • Is the error suggestion not good enough? Commented Oct 21, 2013 at 21:02
  • It may not be if he's new to Java, or programming. Commented Oct 21, 2013 at 21:02
  • Sorry guys - you are too quick ;) - I had some trouble getting the code in the "CODE" section, but it should be good now. Commented Oct 21, 2013 at 21:11

2 Answers 2

3

In your else block, instead of:

new ArrayList<String>() {{ add(**breakdown.getId()**); }} 

you can use:

new ArrayList<String>(Arrays.asList(breakdown.getId()) 

or, since you just want a single element ArrayList, you can use Collections.singletonList that avoids the creation of temporary varargs array:

new ArrayList<String>(Collections.singletonList(breakdown.getId()) 

The { ... } after the new ArrayList<>() creates an anonymous subclass of ArrayList, which is an inner class only. Inside an inner class you cannot access non-final local variables.

Sign up to request clarification or add additional context in comments.

19 Comments

Or new ArrayList<String>(Collections.singletonList(breakdown.getId()). This saves the temporary varargs array.
There's no need to use new ArrayList<String>, just use Arrays.asList(breakdown.getId() (assuming that getId() returns a String).
@LuiggiMendoza I guess that would also be fine here. But just to give OP an equivalent code without change in behaviour I wrote that. asList returns fixed size list right?
In HotSpot, Arrays#asList simply implements this as return new ArrayList<T>(T[] array), so you end creating an ArrayList from another ArrayList.
@Luiggi Mendoza: Then the map´s type LinkedHashMap<String, ArrayList<String>> must be changed to LinkedHashMap<String, List<String>>
|
0

You can ease the code by always retrieving the List value in the for loop, then if it is null create a new one and add it to your Map, otherwise add the value to the list.

for (int i = 0; i < records.length; i++) { List<String> value = sfFundIdsByContact.get(breakdown.getSalesConnect__Contact__c()); if (value == null) { value = new ArrayList<String>(); sfFundIdsByContact.put(breakdown.getSalesConnect__Contact__c(), value); } value.add(breakdown.getId()); } 

As a recommendation, change the definition of

LinkedHashMap<String, ArrayList<String>> sfFundIdsByContact 

to

Map<String, List<String>> sfFundIdsByContact 

Refer to What does it mean to "program to an interface"?

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.