Your code, as written, has several issues with it, but let's focus on the error first.
Explaining the error
You're getting this error because you're trying to get an Id from a List
.
You define accountContact
as a Map<Account, List<Contact>>
, so when accountContact.get(acc)
is evaluated, you get a List<Contact>
.
The offending line of code, partially evaluated, is [an instance of List<Contact>].Id
. Your code is trying to access the Id
class variable of the List
type, and List
has no class variables.
The issues with your code
Using SObjects as the key in a Map
(or as the type specified for a Set
) can be useful, but is not something I'd recommend for beginners. Making any change to the instance of an object used as a key for a Map causes you to lose the ability to retrieve some data from the map.
A Map<Id, List<Contact>>
would be more appropriate.
Your query has a useless filter in it Id != null
. Any record that can be queried will have an Id. No exceptions.
Your query is filtering accounts with more than 0 active contacts, so the if(acc.contacts.size() > 0)
check is redundant
Accessing child records (or the embedded list of child records like you do with acct.contacts.size()
) directly carries some risk with it. Once you have a certain amount of child records, Salesforce would need to perform an internal call to queryMore()
and then throw an exception. The safe way to access child records here is to have a nested loop.
e.g.
for(Account acct :myAccounts){
List<Contact> safeList = new List<Contact>();
for(Contact cont :acct.Contacts){
safeList.add(cont);
}
}
It's hard to tell exactly what you're trying to do with accountContact
, but given that you have if(!accountContact.containsKey(...))
I assume you're trying to put data into the map.
The general pattern used to populate maps looks something like this:
Map<Id, List<ChildObject__c>> parentIdToChildren = new Map<Id, List<ChildObject__c>>();
for(Parent par :myParentList){
// The general idea is to make sure that there will always be something in the map
// (that we can use) after this if() block
// This tries to keep typing and repetition to a minimum, and allows us to skip
// the null checks that other approaches would need to do.
if(!parentIdToChildren.containsKey(par.Id)){
// By putting an empty list into the map (and not trying to immediately add
// the first record), the code to add the first record and the code to add
// all subsequent records becomes the same.
// This allows us to avoid needing an ELSE block
parentIdToChildren.put(par.Id, new List<ChildObject__c>());
}
for(ChildObject__c child :par.Children){
// At this point, parentIdToChildren is guaranteed to have a non-null value
// stored for the map's key (the parent's Id)
// Collections are stored in maps as references, so we can directly call .add()
// without needing to declare a temporary variable to hold the result of
// map.get(<key>)
parentIdToChildren.get(par.Id).add(child);
}
}