I frequently find I want/need to map a list of SObjects by a value other than it's own Id.
So, I'd like to abstract this process to make it reusable.
For example, I might want to map Contacts by Account Id.
So I've created a method mapBySpecifiedIdField:
public static Map<Id, Set<SObject>> mapBySpecifiedIdField (List<SObject> homogeneousSObjectList, SObjectField idField) {
if (homogeneousSObjectList == null || homogeneousSObjectList.isEmpty()) {
return null;
}
Map<Id, Set<SObject>> sObjectSetBySpecifiedIdMap = new Map<Id, Set<SObject>>();
for (SObject sObj : homogeneousSObjectList) {
Id specifiedId = (Id) sObj.get(idField);
if (!String.isBlank(specifiedId)) {
if (!sObjectSetBySpecifiedIdMap.containsKey(sObj.Id)) {
sObjectSetBySpecifiedIdMap.put(sObj.Id, new Set<SObject>());
}
sObjectSetBySpecifiedIdMap.get(sObj.id).add(sObj);
}
}
String mapType = 'Map<Id, Set<' + homogeneousSObjectList[0].getSObjectType() + '>>';
Map<Id, Set<SObject>> concreteSObjectSetByIdMap = (Map<Id, Set<SObject>>)Type.forName(mapType).newInstance();
concreteSObjectSetByIdMap.putAll(sObjectSetBySpecifiedIdMap);
return concreteSObjectSetByIdMap;
}
I'd prefer to invoke it with:
Map<Id, Set<Contact>> mapContactSetByAccountId = (Map<Id, Set<Contact>>) MapHelper.mapBySpecifiedIdField(contactList, Contact.AccountId);
But first, I'll get a compile error:
Incompatible types since an instance of
Map<Id,Set<SObject>>is never an instance ofMap<Id,Set<Contact>>
If I change my invocation to:
Map<Id, Set<Object>> mapContactSetByAccountId = MapHelper.mapBySpecifiedIdField(contactList, Contact.AccountId);
But this results in a runtime error:
System.TypeException: Invalid conversion from runtime type
Map<Id,Set<Contact>>toMap<Id,Set<SObject>>
Is there any way I can make this work?
Set<SObject>as the map value? The problem here lies with trying to upcast a set. If you use aList<SObject>orMap<Id, SObject>in its place, your idea should work. – Derek F Apr 20 '18 at 12:30Listrather thanSet. I stand firmly behind that vote; this question is asking how to accomplish exactly the same end goal. I added links to "why" answers because you disagreed with the closure of this question. It seems hard to believe that either "how" or "why" is unanswered after reading all four questions I have linked. Regardless, this conversation is off topic here. If you would like to further explore whether or not this question is a duplicate, that conversation belongs on Meta. – Adrian Larson Apr 26 '18 at 04:47